def geoserver_upload(self, input_file): print "upload", input_file path, file_ext = os.path.split(input_file) f = os.path.splitext(file_ext)[0] cat = Catalog(self.GEOSERVER_HOST, self.GEOSERVER_USER, self.GEOSERVER_PASSWORD) try: cat.create_coveragestore(name=f, data=input_file, workspace=cat.get_workspace(self.GEOSERVER_WORKSPACE), overwrite=True) except UploadError: print "map already exist" cat.delete(cat.get_layer(f)) cat.delete(cat.get_resources(f, self.GEOSERVER_WORKSPACE)[0]) cat.create_coveragestore(name=f, data=input_file, workspace=cat.get_workspace(self.GEOSERVER_WORKSPACE), overwrite=True)
def wrapper(self, *args, **kwargs): workspace_name = 'geonode' django_datastore = db.connections['datastore'] catalog = Catalog( ogc_server_settings.internal_rest, *ogc_server_settings.credentials ) # Set up workspace/datastore as appropriate ws = catalog.get_workspace(workspace_name) delete_ws = False if ws is None: ws = catalog.create_workspace(workspace_name, 'http://www.geonode.org/') delete_ws = True datastore = create_datastore(workspace_name, django_datastore, catalog) # test method called here try: ret = wrapped_func(self, *args, **kwargs) finally: # Tear down workspace/datastore as appropriate if delete_ws: catalog.delete(ws, recurse=True) else: catalog.delete(datastore, recurse=True) return ret
def upload_impact_vector(impact_file_path): data = dict() try: cat = Catalog(GEOSERVER_REST_URL, GS_USERNAME, GS_PASSWORD) ws = cat.get_workspace(GS_IMPACT_WS) base = str(os.path.splitext(impact_file_path)[0]) name = str(os.path.splitext(os.path.basename(base))[0]) shx = base + '.shx' dbf = base + '.dbf' prj = base + '.prj' data = { 'shp' : impact_file_path, 'shx' : shx, 'dbf' : dbf, 'prj' : prj } cat.create_featurestore(name, data, ws, True) data = {'return': 'success', 'resource' : name } except: return {'return': 'fail'} else: return data
def remove_service(request, service_id): """ Delete a service, and its constituent layers. """ service_obj = get_object_or_404(Service, pk=service_id) if not request.user.has_perm("maps.delete_service", obj=service_obj): return HttpResponse( loader.render_to_string( "401.html", RequestContext(request, {"error_message": _("You are not permitted to remove this service.")}), ), status=401, ) if request.method == "GET": return render_to_response("services/service_remove.html", RequestContext(request, {"service": service_obj})) elif request.method == "POST": # Retrieve this service's workspace from the GeoServer catalog. cat = Catalog(settings.OGC_SERVER["default"]["LOCATION"] + "rest", _user, _password) workspace = cat.get_workspace(service_obj.name) # Delete nested workspace structure from GeoServer for this service. if workspace: for store in cat.get_stores(workspace): for resource in cat.get_resources(store): for layer in cat.get_layers(resource): cat.delete(layer) cat.delete(resource) cat.delete(store) cat.delete(workspace) # Delete service from GeoNode. service_obj.delete() return HttpResponseRedirect(reverse("services"))
class UploaderTests(MapStoryTestMixin): """ Basic checks to make sure pages load, etc. """ def create_datastore(self, connection, catalog): settings = connection.settings_dict params = {'database': settings['NAME'], 'passwd': settings['PASSWORD'], 'namespace': 'http://www.geonode.org/', 'type': 'PostGIS', 'dbtype': 'postgis', 'host': settings['HOST'], 'user': settings['USER'], 'port': settings['PORT'], 'enabled': "True"} store = catalog.create_datastore( settings['NAME'], workspace=self.workspace) store.connection_parameters.update(params) try: catalog.save(store) except FailedRequestError: # assuming this is because it already exists pass return catalog.get_store(settings['NAME']) def setUp(self): if not os.path.exists(os.path.join(os.path.split(__file__)[0], '..', 'importer-test-files')): self.skipTest('Skipping test due to missing test data.') # These tests require geonode to be running on :80! self.postgis = db.connections['datastore'] self.postgis_settings = self.postgis.settings_dict self.username, self.password = self.create_user( 'admin', 'admin', is_superuser=True) self.non_admin_username, self.non_admin_password = self.create_user( 'non_admin', 'non_admin') self.cat = Catalog( ogc_server_settings.internal_rest, *ogc_server_settings.credentials) if self.cat.get_workspace('geonode') is None: self.cat.create_workspace('geonode', 'http://geonode.org') self.workspace = 'geonode' self.datastore = self.create_datastore(self.postgis, self.cat) def tearDown(self): """ Clean up geoserver. """ self.cat.delete(self.datastore, recurse=True)
def add_layer(shp): global ds_name, ws_name, appserver global instance cat = Catalog(appserver + '/rest') ws = cat.get_workspace(ws_name) ds = cat.get_store(ds_name, ws_name) print 'starting {0}...'.format(shp) components = dict((ext, shp + '.' + ext) for ext in ['shp', 'prj', 'shx', 'dbf']) cat.add_data_to_store(ds, shp, components, ws, True) print '{0} finished ...'.format(shp)
def raster_to_geoserver(geoserver_url, raster, workspace): cat = Catalog(geoserver_url, username, password) create_workspace(geoserver_url, username, password, workspace) file_name = os.path.splitext(os.path.basename(raster))[0] workspace = cat.get_workspace(workspace) if not file_name in [l.name for l in cat.get_layers()]: print 'Creating new layer: %s' %file_name cat.create_coveragestore(file_name, raster, workspace) else: print 'Layer %s already exists' %file_name
def geoserver_upload_shape(self, input_file): print "upload", input_file path, file_ext = os.path.split(input_file) cat = Catalog(self.GEOSERVER_HOST, self.GEOSERVER_USER, self.GEOSERVER_PASSWORD) shapeFile = shapefile_and_friends(input_file) print shapeFile cat.create_featurestore(name=file_ext, data=shapeFile, workspace=cat.get_workspace(self.GEOSERVER_WORKSPACE), overwrite=True, charset=None)
def shp_to_geoserver(geoserver_url, shapefile, workspace): cat = Catalog(geoserver_url, username, password) create_workspace(geoserver_url, username, password, workspace) shapefile_plus_sidecars = geoserver.util.shapefile_and_friends(shapefile) file_name = os.path.splitext(os.path.basename(shapefile))[0] workspace = cat.get_workspace(workspace) if not file_name in [l.name for l in cat.get_layers()]: print 'Creating new layer: %s' %file_name cat.create_featurestore(file_name, shapefile_plus_sidecars, workspace) else: print 'Layer %s already exists' %file_name
def upload_raster(impact_file_path): data = dict() try: cat = Catalog(GEOSERVER_REST_URL, GS_USERNAME, GS_PASSWORD) ws = cat.get_workspace(GS_IMPACT_WS) base = str(os.path.splitext(impact_file_path)[0]) name = str(os.path.splitext(os.path.basename(base))[0]) cat.create_coveragestore(name, impact_file_path, ws, True) except: raise
def get_geoserver_cascading_workspace(create=True): """Return the geoserver workspace used for cascaded services The workspace can be created it if needed. """ catalog = Catalog( service_url=settings.OGC_SERVER["default"]["LOCATION"] + "rest", username=settings.OGC_SERVER["default"]["USER"], password=settings.OGC_SERVER["default"]["PASSWORD"] ) name = getattr(settings, "CASCADE_WORKSPACE", "cascaded-services") workspace = catalog.get_workspace(name) if workspace is None and create: uri = "http://www.geonode.org/{}".format(name) workspace = catalog.create_workspace(name, uri) return workspace
def uploadGS(self): shpFile = os.path.join(self.tempFolder, 'diff_simplify') cat = Catalog("http://localhost:8080/geoserver/rest", username="******", password="******") gsWorkspace = cat.get_workspace("SJ") shapefileData = geoserver.util.shapefile_and_friends(shpFile) # TODO: 레이어명 구분이 필요 layerName = self.resId # layerName = time.strftime("%Y%m%d_%H%M%S") cat.create_featurestore(layerName, shapefileData, gsWorkspace) cat.reload() layer = cat.get_layer(layerName) diffStyle = cat.get_style('SJ:diff_style') if diffStyle is not None: layer._set_default_style('SJ:diff_style') cat.save(layer)
def updateGs(self): gs = settings.GEOSERVER cat = Catalog(gs['host'], gs['user'], gs['password']) ws = cat.get_workspace(gs['workspace']) epsg = 'EPSG:404000' for kuva in self.all(): image = kuva.jpgImage path = os.path.join(settings.MEDIA_ROOT, image.name) layerName = kuva.gsName() kuva.createWld() cs = cat.create_coveragestore2(layerName, workspace=ws) cs.url = 'file://' + path cs.type = 'WorldImage' cat.save(cs) coverage = cat.publish_coverage(layerName, cs, epsg) cat.addToGwc(coverage, 'kuva404000')
def main(args): # print args data_path = args.path or DATA_PATH geo_server = args.geoserver or GEOSERVER mosaic_name = args.mosaic or MOSAIC_NAME new_layer = args.layer # eg. '20091201.tif' or '20091201.zip' store_name = args.store or STORE workspace_name = args.workspace or WORKSPACE username = args.user or USERNAME password = args.password or PASSWORD # access geoserver # TODO - in production usage, find another way to access username & password try: gs_catalog = Catalog("%s/geoserver/rest" % geo_server, username=username, password=password) ws = gs_catalog.get_workspace(workspace_name) if not ws: logger.error('Unable to access workspace: "%s"' % workspace_name) return except FailedRequestError, e: logger.error('Unable to access GeoServer.', exc_info=True) return
ts.save() logger.info("[x] File:--%r-- has been successfully imported", src) except Exception, e: logger.error("[x] File:--%r-- failed to be imported", src) data_move(src, ERROR_file) raise Exception( "[x] %r _FAILED to be imported" % src + ' reason--%r' % e) try: logger.debug("[x] Publishing %r to GeoServer", src) cat = Catalog( gs_setting['geoserver_url'] + '/rest', gs_setting['geoserver_username'], gs_setting['geoserver_password'], True) workspace = cat.get_workspace(gs_setting['geoserver_workspace']) if workspace is None: cat.create_workspace( gs_setting['geoserver_workspace'], gs_setting['geoserver_workspace']) str_time = "{:02d}:{:02d}:{:02d}".format( timestamp.hour[0].item(), timestamp.minute[0].item(), timestamp.second[0].item() ) store_name = "{uuid}_{date}T{time}Z".format( uuid=ts.uuid, date=str_date, time=str_time,
class CatalogTests(unittest.TestCase): def setUp(self): self.cat = Catalog(GSPARAMS['GSURL'], username=GSPARAMS['GSUSER'], password=GSPARAMS['GSPASSWORD']) self.gs_version = self.cat.get_short_version() def testGSVersion(self): version = self.cat.get_version() pat = re.compile('\d\.\d+') self.assertTrue(pat.match('2.2.x')) self.assertTrue(pat.match('2.3.2')) self.assertTrue(pat.match('2.3-SNAPSHOT')) self.assertTrue(pat.match(version)) def testWorkspaces(self): self.assertEqual(7, len(self.cat.get_workspaces())) # marking out test since geoserver default workspace is not consistent # self.assertEqual("cite", self.cat.get_default_workspace().name) self.assertEqual("topp", self.cat.get_workspaces(names="topp")[-1].name) self.assertEqual(2, len(self.cat.get_workspaces(names=['topp', 'sde']))) self.assertEqual(2, len(self.cat.get_workspaces(names='topp, sde'))) self.assertEqual("topp", self.cat.get_workspace("topp").name) self.assertIsNone(self.cat.get_workspace("blahblah-")) def testStores(self): self.assertEqual(0, len(self.cat.get_stores(names="nonexistentstore"))) topp = self.cat.get_workspaces("topp")[0] sf = self.cat.get_workspaces("sf")[0] self.assertEqual(9, len(self.cat.get_stores())) self.assertEqual(2, len(self.cat.get_stores(workspaces=topp))) self.assertEqual(2, len(self.cat.get_stores(workspaces=sf))) self.assertEqual(2, len(self.cat.get_stores(workspaces='sf'))) self.assertEqual(2, len(self.cat.get_stores(names='states_shapefile, sfdem'))) self.assertEqual(2, len(self.cat.get_stores(names=['states_shapefile', 'sfdem']))) self.assertEqual("states_shapefile", self.cat.get_stores(names="states_shapefile", workspaces=topp.name)[0].name) self.assertEqual("states_shapefile", self.cat.get_stores(names="states_shapefile")[0].name) self.assertEqual("sfdem", self.cat.get_stores(names="sfdem", workspaces=sf.name)[0].name) self.assertEqual("sfdem", self.cat.get_stores(names="sfdem")[0].name) self.assertEqual("sfdem", self.cat.get_store("sfdem").name) self.assertIsNone(self.cat.get_store("blah+blah-")) def testResources(self): topp = self.cat.get_workspaces("topp")[0] sf = self.cat.get_workspaces("sf")[0] states = self.cat.get_stores(names="states_shapefile", workspaces=topp.name)[0] sfdem = self.cat.get_stores(names="sfdem", workspaces=sf.name)[0] self.assertEqual(19, len(self.cat.get_resources())) self.assertEqual(2, len(self.cat.get_resources(stores=[states.name, sfdem.name]))) self.assertEqual(11, len(self.cat.get_resources(workspaces=[topp.name, sf.name]))) self.assertEqual("states", self.cat.get_resources(names="states", stores=states.name)[0].name) self.assertEqual("states", self.cat.get_resources(names="states", workspaces=topp.name)[0].name) self.assertEqual("states", self.cat.get_resources(names="states")[0].name) self.assertEqual("states", self.cat.get_resource("states").name) self.assertIsNone(self.cat.get_resource("blah+1blah-2")) states = self.cat.get_resources(names="states")[0] fields = [ states.title, states.abstract, states.native_bbox, states.latlon_bbox, states.projection, states.projection_policy ] self.assertFalse(None in fields, str(fields)) self.assertFalse(len(states.keywords) == 0) self.assertFalse(len(states.attributes) == 0) self.assertTrue(states.enabled) self.assertEqual("sfdem", self.cat.get_resources(names="sfdem", stores=sfdem.name)[0].name) self.assertEqual("sfdem", self.cat.get_resources(names="sfdem", workspaces=sf.name)[0].name) self.assertEqual("sfdem", self.cat.get_resources(names="sfdem")[0].name) def testResourcesUpdate(self): res_dest = self.cat.get_resources() count = 0 for rd in res_dest: # only wms layers if rd.resource_type != "wmsLayer": continue # looking for same name ro = self.cat.get_resources(names=rd.name) if ro is not None: rd.title = ro.title rd.abstract = ro.abstract rd.keywords = ro.keywords rd.projection = ro.projection rd.native_bbox = ro.native_bbox rd.latlon_bbox = ro.latlon_bbox rd.projection_policy = ro.projection_policy rd.enabled = ro.enabled rd.advertised = ro.advertised rd.metadata_links = ro.metadata_links or None self.cat.save(rd) self.cat.reload() count += 1 def testLayers(self): if self.gs_version >= "2.13": expected = set([ 'sf:roads', 'sf:sfdem', 'nurc:mosaic', 'tiger:giant_polygon', 'sf:bugsites', 'topp:states', 'sf:streams', 'tiger:poly_landmarks', 'tiger:poi', 'topp:tasmania_water_bodies', 'tiger:tiger_roads', 'topp:tasmania_roads', 'nurc:Pk50095', 'topp:tasmania_cities', 'nurc:Img_Sample', 'sf:restricted', 'nurc:Arc_Sample', 'sf:archsites', 'topp:tasmania_state_boundaries' ]) else: expected = set([ "Arc_Sample", "Pk50095", "Img_Sample", "mosaic", "sfdem", "bugsites", "restricted", "streams", "archsites", "roads", "tasmania_roads", "tasmania_water_bodies", "tasmania_state_boundaries", "tasmania_cities", "states", "poly_landmarks", "tiger_roads", "poi", "giant_polygon" ]) actual = set(l.name for l in self.cat.get_layers()) missing = expected - actual extras = actual - expected message = "Actual layer list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing) self.assert_(len(expected ^ actual) == 0, message) states = self.cat.get_layer("states") self.assert_("states", states.name) self.assert_(isinstance(states.resource, ResourceInfo)) self.assertEqual(set(s.name for s in states.styles), set(['pophatch', 'polygon'])) self.assertEqual(states.default_style.name, "population") def testLayerGroups(self): expected = set(["tasmania", "tiger-ny", "spearfish"]) actual = set(l.name for l in self.cat.get_layergroups(names=["tasmania", "tiger-ny", "spearfish"])) missing = expected - actual extras = actual - expected message = "Actual layergroup list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing) self.assert_(len(expected ^ actual) == 0, message) tas = self.cat.get_layergroups(names="tasmania")[0] self.assert_("tasmania", tas.name) self.assert_(isinstance(tas, LayerGroup)) if self.gs_version >= "2.13": self.assertEqual(tas.layers, [ 'topp:tasmania_state_boundaries', 'topp:tasmania_water_bodies', 'topp:tasmania_roads', 'topp:tasmania_cities' ], tas.layers) else: self.assertEqual(tas.layers, [ 'tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities' ], tas.layers) self.assertEqual(tas.styles, [None, None, None, None], tas.styles) # Try to create a new Layer Group into the "topp" workspace self.assert_(self.cat.get_workspaces("topp")[0] is not None) tas2 = self.cat.create_layergroup("tasmania_reloaded", tas.layers, workspace = "topp") self.cat.save(tas2) self.assertEqual(1, len(self.cat.get_layergroups(names='tasmania_reloaded', workspaces="topp"))) tas2 = self.cat.get_layergroups(names='tasmania_reloaded', workspaces="topp")[0] self.assert_("tasmania_reloaded", tas2.name) self.assert_(isinstance(tas2, LayerGroup)) self.assertEqual(tas2.workspace, "topp", tas2.workspace) if self.gs_version >= "2.13": self.assertEqual(tas2.layers, [ 'topp:tasmania_state_boundaries', 'topp:tasmania_water_bodies', 'topp:tasmania_roads', 'topp:tasmania_cities' ], tas2.layers) else: self.assertEqual(tas2.layers, [ 'tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities' ], tas2.layers) self.assertEqual(tas2.styles, [None, None, None, None], tas2.styles) def testStyles(self): self.assertEqual("population", self.cat.get_styles("population")[0].name) self.assertEqual("popshade.sld", self.cat.get_styles("population")[0].filename) self.assertEqual("population", self.cat.get_styles("population")[0].sld_name) self.assertEqual("population", self.cat.get_style("population").sld_name) self.assertIsNone(self.cat.get_style("blah+#5blah-")) self.assertEqual(0, len(self.cat.get_styles('non-existing-style'))) def testEscaping(self): # GSConfig is inconsistent about using exceptions vs. returning None # when a resource isn't found. # But the basic idea is that none of them should throw HTTP errors from # misconstructed URLS self.cat.get_styles("best style ever") self.cat.get_workspaces("best workspace ever") self.assertEqual(0, len(self.cat.get_stores(workspaces="best workspace ever", names="best store ever"))) self.cat.get_layer("best layer ever") self.cat.get_layergroups("best layergroup ever") def testUnicodeUrl(self): """ Tests that the geoserver.support.url function support unicode strings. """ # Test the url function with unicode seg = ['workspaces', 'test', 'datastores', u'operaci\xf3n_repo', 'featuretypes.xml'] u = build_url(base=self.cat.service_url, seg=seg) self.assertEqual(u, self.cat.service_url + "/workspaces/test/datastores/operaci%C3%B3n_repo/featuretypes.xml") # Test the url function with normal string seg = ['workspaces', 'test', 'datastores', 'test-repo', 'featuretypes.xml'] u = build_url(base=self.cat.service_url, seg=seg) self.assertEqual(u, self.cat.service_url + "/workspaces/test/datastores/test-repo/featuretypes.xml")
class GeoserverHelper: def __init__(self, geoserverUrl="", geoserverUserName="", geoserverPW="", geoserverWorkSpace="", postgreIP="", postgreUserName="", postgrePW=""): """use the constructor given arguments if used""" self.geoserverUrl = geoserverUrl if geoserverUrl != "" else GEOSERVERURL self.geoserverUserName = geoserverUserName if geoserverUserName != "" else GEOSERVERUSERNAME self.geoserverPW = geoserverPW if geoserverPW != "" else GEOSERVERPW self.geoserverWorkSpace = geoserverWorkSpace if geoserverWorkSpace != "" else "crc" self.postgreIP = postgreIP if postgreIP != "" else POSTGREIP self.postgreUserName = postgreUserName if postgreUserName != "" else POSTGREUSERNAME self.postgrePW = postgrePW if postgrePW != "" else POSTGREPW if self.geoserverUrl[-1] != '/': raise Exception("GeoserverUrl must end with a slash ('/')") self.catalog = Catalog(self.geoserverUrl + "rest/") self.catalog.http.add_credentials(self.geoserverUserName, self.geoserverPW) try: workspaces = self.catalog.get_workspaces() except: e = sys.exc_info()[0] print e self.cWorkSpace = self.catalog.get_workspace(self.geoserverWorkSpace) def getLayers(self): return self.cWorkSpace.catalog.get_layers() def insertShapeIntoPostGis(self, shapeFile, databaseName, tableName, encoding=3857): '''returns the returnCode of the execution of the insert script, e.g: helper.insertShapeIntoPostGis('/home/c815/gsTest/test.shp','crc','testingHelper2')''' if not os.path.isfile(shapeFile): print "Shape file not found" return -1 cmds = "PGPASSWORD={pgPW} ./createWSFTFromSHP.sh -s {shapeFileF} -d {databaseNameF} -t {tableNameF} -u {postgreUsername} -i {postgreIP}".format( pgPW=self.postgrePW, shapeFileF=shapeFile, databaseNameF=databaseName, tableNameF=tableName, postgreUsername=self.postgreUserName, postgreIP=self.postgreIP) return subprocess.call(cmds, shell=True) def uploadShapeFile(self, shapeFile, storeName): shpPlusSidcars = geoserver.util.shapefile_and_friends(shapeFile[:-3]) shpPlusSidcars self.ft = self.catalog.create_featurestore(storeName, shpPlusSidcars, self.cWorkSpace) def getStyles(self): return self.catalog.get_styles() def uploadStyleFile(self, sldFile, styleName, overWrite, workSpace=None): f = open(sldFile, 'r') styleSrc = f.read() uploadStyle(styleSrc, styleName, overWrite, workSpace) f.close() def uploadStyle(self, sldSrc, styleName, overWrite, workSpace=None): self.catalog.create_style(styleName, sldSrc, overWrite, workSpace) def publishPostGISLayer(self, postGISLayerName, storeName, crs='EPSG:3857'): '''cat.publish_featuretype('testingstuff',crcStore,native_crs='EPSG:3857')''' store = self.catalog.get_store(storeName) if store != None: self.catalog.publish_featuretype(postGISLayerName, store, crs) def setDefaultStyleForLayer(self, layerName, styleName): l = self.catalog.get_layer(layerName) sNames = [i.name for i in self.getStyles()] if styleName not in sNames: split = styleName.split(':') if len(split) == 2: workSpace = styleName.split(':')[0] newStyleName = styleName.split(':')[1] else: return -1 style = self.catalog.get_style(newStyleName, workSpace) if style is None: return -1 if l != None: l._set_default_style(styleName) self.catalog.save(l) return 0 def createPostGISDataStore(self, storeName, postGisPassword, postGisUser, postGisHost, postGisDatabase, workSpace=None): #check if connection parameter are valid try: conn = psycopg2.connect( "dbname='{dbName}' user='******' host='{Host}' password='******'" .format(dbName=postGisDatabase, dbUser=postGisUser, Host=postGisHost, password=postGisPassword)) except: return False w = self.catalog.create_datastore(storeName, workSpace) template = Template( """{'validate connections': 'true', 'port': '5432', 'Support on the fly geometry simplification': 'true', 'create database': 'false', 'dbtype': 'postgis', 'Connection timeout': '20', 'namespace': 'http://www.crcproject.com', 'Max connection idle time': '300', 'Expose primary keys': 'false', 'min connections': '1', 'Max open prepared statements':'50', 'passwd': '$passwd', 'encode functions': 'false', 'max connections': '10', 'Evictor tests per run': '3', 'Loose bbox': 'true', 'Evictor run periodicity': '300', 'Estimated extends': 'true', 'database': '$database', 'fetch size': '1000', 'Test while idle': 'true', 'host': '$host', 'preparedStatements': 'false', 'schema': 'public', 'user': '******'}""") dic = ast.literal_eval( template.substitute(passwd=postGisPassword, user=postGisUser, host=postGisHost, database=postGisDatabase)) #'passwd': 'crypt1:Bsaz2AUI8T+6Pj43krA7kg==', #'user': '******'} #'database': 'crc', #'host': 'localhost', w.connection_parameters = dic self.catalog.save(w) return True
def _register_cascaded_layers(service, owner=None): """ Register layers for a cascading WMS """ if service.type == 'WMS' or service.type == "OWS": cat = Catalog(settings.OGC_SERVER['default']['LOCATION'] + "rest", _user, _password) # Can we always assume that it is geonode? # Should cascading layers have a separate workspace? cascade_ws = cat.get_workspace(service.name) if cascade_ws is None: cascade_ws = cat.create_workspace(service.name, 'cascade') try: store = cat.get_store(service.name, cascade_ws) except Exception: store = cat.create_wmsstore(service.name, cascade_ws) cat.save(store) wms = WebMapService(service.base_url) layers = list(wms.contents) count = 0 for layer in layers: lyr = cat.get_resource(layer, store, cascade_ws) if lyr is None: if service.type in ["WMS", "OWS"]: resource = cat.create_wmslayer(cascade_ws, store, layer) elif service.type == "WFS": resource = cat.create_wfslayer(cascade_ws, store, layer) if resource: bbox = resource.latlon_bbox cascaded_layer, created = Layer.objects.get_or_create( typename="%s:%s" % (cascade_ws.name, resource.name), service=service, defaults={ "name": resource.name, "workspace": cascade_ws.name, "store": store.name, "storeType": store.resource_type, "title": resource.title or 'No title provided', "abstract": resource.abstract or 'No abstract provided', "owner": None, "uuid": str(uuid.uuid4()), "bbox_x0": bbox[0], "bbox_x1": bbox[1], "bbox_y0": bbox[2], "bbox_y1": bbox[3], }) if created: cascaded_layer.save() if cascaded_layer is not None and cascaded_layer.bbox is None: cascaded_layer._populate_from_gs( gs_resource=resource) cascaded_layer.set_default_permissions() service_layer, created = ServiceLayer.objects.get_or_create( service=service, typename=cascaded_layer.name ) service_layer.layer = cascaded_layer service_layer.title = cascaded_layer.title, service_layer.description = cascaded_layer.abstract, service_layer.styles = cascaded_layer.styles service_layer.save() count += 1 else: logger.error( "Resource %s from store %s could not be saved as layer" % (layer, store.name)) message = "%d Layers Registered" % count return_dict = {'status': 'ok', 'msg': message} return HttpResponse(json.dumps(return_dict), mimetype='application/json', status=200) elif service.type == 'WCS': return HttpResponse('Not Implemented (Yet)', status=501) else: return HttpResponse('Invalid Service Type', status=400)
def gs_slurp(ignore_errors=True, verbosity=1, console=None, owner=None, workspace=None, store=None, filter=None, skip_unadvertised=False, remove_deleted=False): """Configure the layers available in GeoServer in GeoNode. It returns a list of dictionaries with the name of the layer, the result of the operation and the errors and traceback if it failed. """ # avoid circular import problem from geonode.layers.models import set_attributes if console is None: console = open(os.devnull, 'w') if verbosity > 1: print >> console, "Inspecting the available layers in GeoServer ..." cat = Catalog(ogc_server_settings.internal_rest, _user, _password) if workspace is not None: workspace = cat.get_workspace(workspace) if workspace is None: resources = [] else: resources = cat.get_resources(workspace=workspace) elif store is not None: store = cat.get_store(store) resources = cat.get_resources(store=store) else: resources = cat.get_resources(workspace=workspace) if remove_deleted: resources_for_delete_compare = resources[:] workspace_for_delete_compare = workspace # filter out layers for delete comparison with GeoNode layers by following criteria: # enabled = true, if --skip-unadvertised: advertised = true, but disregard the filter parameter in the case of deleting layers resources_for_delete_compare = [ k for k in resources_for_delete_compare if k.enabled == "true" ] if skip_unadvertised: resources_for_delete_compare = [ k for k in resources_for_delete_compare if k.advertised == "true" or k.advertised == True or k.advertised is None ] if filter: resources = [k for k in resources if filter in k.name] # filter out layers depending on enabled, advertised status: resources = [k for k in resources if k.enabled == "true"] if skip_unadvertised: resources = [ k for k in resources if k.advertised == "true" or k.advertised == True or k.advertised is None ] # TODO: Should we do something with these? # i.e. look for matching layers in GeoNode and also disable? disabled_resources = [k for k in resources if k.enabled == "false"] number = len(resources) if verbosity > 1: msg = "Found %d layers, starting processing" % number print >> console, msg output = { 'stats': { 'failed': 0, 'updated': 0, 'created': 0, 'deleted': 0, }, 'layers': [], 'deleted_layers': [] } start = datetime.datetime.now() for i, resource in enumerate(resources): name = resource.name store = resource.store workspace = store.workspace try: # Avoid circular import problem from geonode.layers.models import Layer layer, created = Layer.objects.get_or_create( name=name, defaults={ "workspace": workspace.name, "store": store.name, "storeType": store.resource_type, "typename": "%s:%s" % (workspace.name.encode('utf-8'), resource.name.encode('utf-8')), "title": resource.title or 'No title provided', "abstract": resource.abstract or 'No abstract provided', "owner": owner, "uuid": str(uuid.uuid4()) }) layer.save() # recalculate the layer statistics set_attributes(layer, overwrite=True) except Exception, e: if ignore_errors: status = 'failed' exception_type, error, traceback = sys.exc_info() else: if verbosity > 0: msg = "Stopping process because --ignore-errors was not set and an error was found." print >> sys.stderr, msg raise Exception( 'Failed to process %s' % resource.name.encode('utf-8'), e), None, sys.exc_info()[2] else: if created: layer.set_default_permissions() status = 'created' output['stats']['created'] += 1 else: status = 'updated' output['stats']['updated'] += 1 msg = "[%s] Layer %s (%d/%d)" % (status, name, i + 1, number) info = {'name': name, 'status': status} if status == 'failed': output['stats']['failed'] += 1 info['traceback'] = traceback info['exception_type'] = exception_type info['error'] = error output['layers'].append(info) if verbosity > 0: print >> console, msg
elif (passedTime > uploadTimeOut): logging.error('TIMEOUT: Failed to upload NetCDF File') exit(1) else: time.sleep(1) cat.reload() passedTime += 1 # ensure AdvancedProjectionSetting is turned off (if not -> layers wont display layers correctly)??? r_set_wms_options = session.put(geoserver_url + '/services/wms/settings', data='<wms><metadata><entry key="advancedProjectionHandling">false</entry></metadata></wms>', headers=headers_xml) # Delete old workspace and create new one if cat.get_workspace(workspace): if cat.get_store(projectName, workspace): test=cat.get_store(projectName, workspace) cat.delete(cat.get_store(projectName, workspace=workspace), purge="all", recurse=True) cat.delete(cat.get_workspace(workspace), purge="all", recurse=True) for layer in cat.get_layers(): if layer.name.startswith(workspace): cat.delete(layer, recurse=True) for style in cat.get_styles(workspaces=[workspace]): cat.delete(style, recurse=True) cat.create_workspace(workspace, geoserver_url + '/' + workspace) # zip the ncFile zfile = cfg['general']['workdir'] + '/outputFiles/data.zip' logging.info('Writing Zipfile ' + zfile) output = zipfile.ZipFile(zfile, 'w')
def main(): # 主要使用 gsconfig 实现 # 1- 创建指定的命名空间 # cat = Catalog(url, username=USER_NAME, password=PWD) ws = cat.create_workspace(WORK_SPACE, WORK_SPACE) # 2- TODO:[*] 创建store——暂时放弃使用 catalog create的方式,还是直接rest的方式 # ds=cat.create_datastore('testStore',WORK_SPACE) # ds.connection_parameters.update() # 2- 提交store存储 coveragestore = 'st_3' headers_xml = {'content-type': 'text/xml'} # TODO:[*] 20-03-04 注意此处存在的问题: 若提交非geoserver 服务所在的路径下的data,会提示错误 file_path = r'file:nmefc/waterwind/nmefc_2016072112_opdr.nc' # 注意 f-string 多行也适用 store_xml=f''' <coverageStore> <name>{coveragestore}</name> <description>风场处理后的数据</description> <type>NetCDF</type> <enabled>true</enabled> <workspace> <name>{WORK_SPACE}</name> </workspace> <__default>false</__default> <url>file:{file_path}</url> <coverages> </coverages> </coverageStore> ''' r_create_coveragestore = requests.post( f'http://*****:*****@key": "COVERAGE_VIEW", "coverageView": { "coverageBands": { "coverageBand": [{ "inputCoverageBands": { "@class": "singleton-list", "inputCoverageBand": [{ "coverageName": "x_wind_10m" }] }, "definition": "x_wind_10m", "index": 0, "compositionType": "BAND_SELECT" }, { "inputCoverageBands": { "@class": "singleton-list", "inputCoverageBand": [{ "coverageName": "y_wind_10m" }] }, "definition": "y_wind_10m", "index": 1, "compositionType": "BAND_SELECT" }] }, "name": "ceshi_0305_03", "envelopeCompositionType": "INTERSECTION", "selectedResolution": "BEST", "selectedResolutionIndex": -1 } }, { "@key": "cachingEnabled", "$": "false" }, { "@key": "dirName", "$": "nmefc_wind_dir_xy_ceshi_0305_03 }] }, "store": { "@class": "coverageStore", "name": "{WORK_SPACE}:{store_name}", "href": "http:\/\/localhost:8082\/geoserver\/rest\/workspaces\/{WORK_SPACE}\/coveragestores\/{store_name}.json" }, "nativeFormat": "NetCDF", "supportedFormats": { "string": ["GEOTIFF", "GIF", "PNG", "JPEG", "TIFF"] }, "interpolationMethods": { "string": ["nearest neighbor", "bilinear", "bicubic"] }, "defaultInterpolationMethod": "nearest neighbor", "dimensions": { "coverageDimension": [{ "name": "x_wind_10m", "description": "GridSampleDimension[-Infinity,Infinity]", "range": { "min": "-inf", "max": "inf" }, "dimensionType": { "name": "REAL_32BITS" } }, { "name": "y_wind_10m", "description": "GridSampleDimension[-Infinity,Infinity]", "range": { "min": "-inf", "max": "inf" }, "dimensionType": { "name": "REAL_32BITS" } }] }, "requestSRS": { "string": ["EPSG:4326"] }, "responseSRS": { "string": ["EPSG:4326"] }, "parameters": { "entry": [{ "string": "Bands", "null": "" }, { "string": "Filter", "null": "" }] }, "nativeCoverageName": "ceshi_0305_03" } } ''' # TODO:[-] 20-03-05 此种方式可以提交,但只有一路band json_str=''' <coverage> <title>st_4</title> <name>st_4</name> <metadata> <entry key="time"> <coverageView> <coverageBands> <coverageBand> <inputCoverageBands> <inputCoverageBand> <coverageName>x_wind_10m</coverageName> </inputCoverageBand> </inputCoverageBands> <definition>x_wind_10m</definition> <index>0</index> <compositionType>BAND_SELECT</compositionType> </coverageBand> </coverageBands> </coverageView> </entry> </metadata> <grid dimension="2"> <range> <low>0 0</low> <high>251 251</high> </range> <transform> <scaleX>0.2</scaleX> <scaleY>-0.2</scaleY> <shearX>0.0</shearX> <shearY>0.0</shearY> <translateX>100.0</translateX> <translateY>50.0</translateY> </transform> <crs>EPSG:4326</crs> </grid> <supportedFormats> <string>GEOTIFF</string> <string>GIF</string> <string>PNG</string> <string>JPEG</string> <string>TIFF</string> </supportedFormats> <enabled>true</enabled> <dimensions> <coverageDimension> <name>x_wind_10m</name> <dimensionType> <name>REAL_32BITS</name> </dimensionType> </coverageDimension> <coverageDimension> <name>y_wind_10m</name> <dimensionType> <name>REAL_32BITS</name> </dimensionType> </coverageDimension> </dimensions> <nativeFormat>NetCDF</nativeFormat> <defaultInterpolationMethod>nearest neighbor</defaultInterpolationMethod> <srs>EPSG:4326</srs> <requestSRS> <string>EPSG:4326</string> </requestSRS> <responseSRS> <string>EPSG:4326</string> </responseSRS> <nativeCoverageName>x_wind_10m</nativeCoverageName> </coverage> ''' # json_str = '''<coverage> # <title>{coveragestore}</title> # <metadata> # <entry key="time"> # <dimensionInfo> # <enabled>true</enabled> # <attribute>time_attribute</attribute> # <presentation>LIST</presentation> # <units>ISO8601</units> # <defaultValue>NONE</defaultValue> # </dimensionInfo> # <coverageView> # <coverageBands> # <inputCoverageBands> # <inputCoverageBand> # <coverageName>wind</coverageName> # </inputCoverageBand> # </inputCoverageBands> # <definition>x_wind_10m</definition> # <index>0</index> # </coverageBands> # </coverageView> # </entry> # </metadata> # <enabled>true</enabled> # </coverage> # ''' # # # data = { # 'a': 123, # 'b': 123 # } # import json # json_temp = json.dumps(data) coverage_title='ceshi_coverage_01' store_name='nmefc_wind' # TODO:此种方式提交的有多路band json_coverage_new=f''' <coverage> <name>{coverage_title}</name> <nativeName>{coverage_title}</nativeName> <namespace> <name>{WORK_SPACE}</name> <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8082/geoserver/rest/namespaces/{WORK_SPACE}.xml" type="application/xml"/> </namespace> <title>{coverage_title}</title> <description>Generated from NetCDF</description> <keywords> <string>{coverage_title}</string> <string>WCS</string> <string>NetCDF</string> </keywords> <nativeCRS>GEOGCS["WGS 84", DATUM["World Geodetic System 1984", SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], AUTHORITY["EPSG","6326"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","4326"]]</nativeCRS> <srs>EPSG:4326</srs> <nativeBoundingBox> <minx>99.9</minx> <maxx>150.10000000000002</maxx> <miny>-0.1</miny> <maxy>50.1</maxy> <crs>EPSG:4326</crs> </nativeBoundingBox> <latLonBoundingBox> <minx>99.9</minx> <maxx>150.10000000000002</maxx> <miny>-0.1</miny> <maxy>50.1</maxy> <crs>EPSG:4326</crs> </latLonBoundingBox> <projectionPolicy>REPROJECT_TO_DECLARED</projectionPolicy> <enabled>true</enabled> <metadata> <entry key="COVERAGE_VIEW"> <coverageView> <coverageBands> <coverageBand> <inputCoverageBands class="singleton-list"> <inputCoverageBand> <coverageName>x_wind_10m</coverageName> </inputCoverageBand> </inputCoverageBands> <definition>x_wind_10m</definition> <index>0</index> <compositionType>BAND_SELECT</compositionType> </coverageBand> <coverageBand> <inputCoverageBands class="singleton-list"> <inputCoverageBand> <coverageName>y_wind_10m</coverageName> </inputCoverageBand> </inputCoverageBands> <definition>y_wind_10m</definition> <index>1</index> <compositionType>BAND_SELECT</compositionType> </coverageBand> </coverageBands> <name>{coverage_title}</name> <envelopeCompositionType>INTERSECTION</envelopeCompositionType> <selectedResolution>BEST</selectedResolution> <selectedResolutionIndex>-1</selectedResolutionIndex> </coverageView> </entry> <entry key="cachingEnabled">false</entry> <entry key="dirName">nmefc_wind_dir_xy_view_nmefc_wind</entry> </metadata> <store class="coverageStore"> <name>{WORK_SPACE}:{store_name}</name> <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8082/geoserver/rest/workspaces/{WORK_SPACE}/coveragestores/{store_name}.xml" type="application/xml"/> </store> <nativeFormat>NetCDF</nativeFormat> <grid dimension="2"> <range> <low>0 0</low> <high>251 251</high> </range> <transform> <scaleX>0.2</scaleX> <scaleY>-0.2</scaleY> <shearX>0.0</shearX> <shearY>0.0</shearY> <translateX>100.0</translateX> <translateY>50.0</translateY> </transform> <crs>EPSG:4326</crs> </grid> <supportedFormats> <string>GEOTIFF</string> <string>GIF</string> <string>PNG</string> <string>JPEG</string> <string>TIFF</string> </supportedFormats> <interpolationMethods> <string>nearest neighbor</string> <string>bilinear</string> <string>bicubic</string> </interpolationMethods> <defaultInterpolationMethod>nearest neighbor</defaultInterpolationMethod> <dimensions> <coverageDimension> <name>x_wind_10m</name> <description>GridSampleDimension[-Infinity,Infinity]</description> <range> <min>-inf</min> <max>inf</max> </range> <dimensionType> <name>REAL_32BITS</name> </dimensionType> </coverageDimension> <coverageDimension> <name>y_wind_10m</name> <description>GridSampleDimension[-Infinity,Infinity]</description> <range> <min>-inf</min> <max>inf</max> </range> <dimensionType> <name>REAL_32BITS</name> </dimensionType> </coverageDimension> </dimensions> <requestSRS> <string>EPSG:4326</string> </requestSRS> <responseSRS> <string>EPSG:4326</string> </responseSRS> <parameters> <entry> <string>Bands</string> <null/> </entry> <entry> <string>Filter</string> <null/> </entry> </parameters> <nativeCoverageName>{coverage_title}</nativeCoverageName> </coverage> ''' json_coverage_merage=''' <coverage><name>ceshi_coverage_01</name><nativeName>ceshi_coverage_01</nativeName><namespace><name>ceshi</name><atom>ceshi</atom></namespace><title>ceshi_coverage_01</title><nativeCoverageName>ceshi_coverage_01</nativeCoverageName><enabled>true</enabled><nativeFormat>NetCDF</nativeFormat><requestSRS><string>EPSG:4326</string></requestSRS><responseSRS><string>EPSG:4326</string></responseSRS><defaultInterpolationMethod>nearest neighbor</defaultInterpolationMethod><metadata><entry key="COVERAGE_VIEW"><coverageView><name>ceshi_coverage_01</name><envelopeCompositionType>INTERSECTION</envelopeCompositionType><selectedResolution /><selectedResolutionIndex>-1</selectedResolutionIndex><coverageBands><coverageBand><definition>x_wind_10m</definition><index>0</index><inputcoveragebands><inputcoverageband><coverageName>x_wind_10m</coverageName></inputcoverageband></inputcoveragebands></coverageBand><coverageBand><definition>ceshi</definition><index>1</index><inputcoveragebands><inputcoverageband><coverageName>y_wind_10m</coverageName></inputcoverageband></inputcoveragebands></coverageBand></coverageBands></coverageView></entry><entry key="cachingEnabled">false</entry><entry key="dirName">nmefc_wind_dir_xy_view_nmefc_wind</entry></metadata><store class="coverageStore"><name>my_test_2:nmefc_2016072112_opdr</name></store><dimensions><coverageDimension><name>x_wind_10m</name><description>GridSampleDimension[-Infinity,Infinity]</description><dimensionType><name>REAL_32BITS</name></dimensionType><range><min>-inf</min><max>inf</max></range></coverageDimension><coverageDimension><name>y_wind_10m</name><description>GridSampleDimension[-Infinity,Infinity]</description><dimensionType><name>REAL_32BITS</name></dimensionType><range><min>-inf</min><max>inf</max></range></coverageDimension></dimensions></coverage> ''' headers_xml_json = {'Content-Type': 'application/json'} response = requests.post( f'http://localhost:8082/geoserver/rest/workspaces/{WORK_SPACE}/coveragestores/{coveragestore}/coverages', auth=('admin', 'geoserver'), # TODO:[*] 20-03-05 此处的问题是对于一个栅格数据有多个特征时,如何添加 对应的name # data='<coverage><nativeCoverageName>x_wind_10m</nativeCoverageName><name>x_wind_10m</name></coverage><coverage><nativeCoverageName>y_wind_10m</nativeCoverageName><name>x_wind_10m</name></coverage>', # TODO:[*] 20-03-19 使用自动拼接的xml,此部分暂时注释掉 # data=json_coverage_new, data=json_coverage_merage, headers=headers_xml) pass # 5 绑定样式 # TODO:[-] 20-03-08 绑定样式的api要参考:大体思路是 -> 工作区->layer->修改默认style(注意不能创建) # PUT /workspaces/{workspaceName}/layers/{layerName} Modify a layer. # https://docs.geoserver.org/latest/en/api/#/latest/en/api/1.0.0/layers.yaml # curl -v -u admin:geoserver -XPUT -H "Content-type: text/xml" -d "<layer><defaultStyle><name>RH2Style</name></defaultStyle></layer>" http://localhost:8090/geoserver/rest/layers/RH2 style_name='wind_dir_style' json_style=f''' <defaultStyle> <name>{WORK_SPACE}:{style_name}</name> <workspace>{WORK_SPACE}</workspace> <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8082/geoserver/rest/workspaces/{WORK_SPACE}/styles/{style_name}.xml" type="application/xml"/> </defaultStyle> ''' json_style_2 = f''' <layer> <defaultStyle> <name>{style_name}</name> </defaultStyle> </layer> ''' url_style=f'http://localhost:8082/geoserver/rest//workspaces/{WORK_SPACE}/layers/{coverage_title}' response=requests.put( url_style, auth=('admin', 'geoserver'), data=json_style_2, headers=headers_xml) pass
class GeoServerDatasetEngineEnd2EndTests(unittest.TestCase): def setUp(self): # Files self.tests_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) self.files_root = os.path.join(self.tests_root, 'files') # GeoServer self.gs_endpoint = TEST_GEOSERVER_DATASET_SERVICE['ENDPOINT'] self.gs_username = TEST_GEOSERVER_DATASET_SERVICE['USERNAME'] self.gs_password = TEST_GEOSERVER_DATASET_SERVICE['PASSWORD'] self.catalog = GeoServerCatalog(self.gs_endpoint, username=self.gs_username, password=self.gs_password) # Postgis self.pg_username = TEST_POSTGIS_SERVICE['USERNAME'] self.pg_password = TEST_POSTGIS_SERVICE['PASSWORD'] self.pg_database = TEST_POSTGIS_SERVICE['DATABASE'] self.pg_table_name = 'points' self.pg_host = TEST_POSTGIS_SERVICE['HOST'] self.pg_port = TEST_POSTGIS_SERVICE['PORT'] self.pg_url = TEST_POSTGIS_SERVICE['URL'] self.pg_public_url = TEST_POSTGIS_SERVICE['PUBLIC_URL'] # Setup a testing workspace self.workspace_name = random_string_generator(10) self.workspace_uri = 'http://www.tethysplatform.org/{}'.format(self.workspace_name) retries = 5 while retries > 0: try: self.catalog.create_workspace(self.workspace_name, self.workspace_uri) break except AssertionError as e: if 'Error persisting' in str(e) and retries > 0: print("WARNING: FAILED TO PERSIST WORKSPACE.") retries -= 1 else: raise # Setup Postgis database connection self.public_engine = create_engine(self.pg_public_url) self.connection = self.public_engine.connect() self.transaction = self.connection.begin() # Create GeoServer Engine self.endpoint = TEST_GEOSERVER_DATASET_SERVICE['ENDPOINT'] self.geoserver_engine = GeoServerSpatialDatasetEngine(endpoint=self.endpoint, username=TEST_GEOSERVER_DATASET_SERVICE['USERNAME'], password=TEST_GEOSERVER_DATASET_SERVICE['PASSWORD']) self.geometry_column = 'geometry' self.geometry_type = 'Point' self.srid = 4326 def assert_valid_response_object(self, response_object): # Response object should be a dictionary with the keys 'success' and either 'result' if success is True # or 'error' if success is False self.assertIsInstance(response_object, dict) self.assertIn('success', response_object) if isinstance(response_object, dict) and 'success' in response_object: if response_object['success'] is True: self.assertIn('result', response_object) elif response_object['success'] is False: self.assertIn('error', response_object) def tearDown(self): # Clean up GeoServer workspace = self.catalog.get_workspace(self.workspace_name) self.catalog.delete(workspace, recurse=True, purge=True) # Clean up Postgis database self.transaction.rollback() self.connection.close() self.public_engine.dispose() def setup_postgis_table(self): """ Creates table in the database named "points" with two entries. The table has three columns: "id", "name", and "geometry." Use this table for the tests that require a database. """ # Clean up delete_sql = "DROP TABLE IF EXISTS {table}".\ format(table=self.pg_table_name) self.connection.execute(delete_sql) # Create table geom_table_sql = "CREATE TABLE IF NOT EXISTS {table} (" \ "id integer CONSTRAINT points_primary_key PRIMARY KEY, " \ "name varchar(20)" \ "); " \ "SELECT AddGeometryColumn('public', '{table}', 'geometry', 4326, 'POINT', 2);". \ format(table=self.pg_table_name) self.connection.execute(geom_table_sql) insert_sql = "INSERT INTO {table} VALUES ({id}, '{name}', ST_GeomFromText('POINT({lon} {lat})', 4326));" rows = [ {"id": 1, "name": "Aquaveo", "lat": 40.276039, "lon": -111.651120}, {"id": 2, "name": "BYU", "lat": 40.252335, "lon": -111.649326}, ] for r in rows: sql = insert_sql.format( table=self.pg_table_name, id=r['id'], name=r['name'], lat=r['lat'], lon=r['lon'] ) self.connection.execute(sql) self.transaction.commit() def test_create_shapefile_resource_base(self): # call methods: create_shapefile_resource, list_resources, get_resource, delete_resource # TEST create shapefile # Setup filename = 'test' shapefile_name = os.path.join(self.files_root, 'shapefile', filename) workspace = self.workspace_name store_id = random_string_generator(10) store_id_name = '{}:{}'.format(workspace, store_id) # store_id_name = store_id # Execute response = self.geoserver_engine.create_shapefile_resource(store_id=store_id_name, shapefile_base=shapefile_name, overwrite=True) # Validate response object self.assert_valid_response_object(response) # Should succeed self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) self.assertIn(store_id, r['name']) self.assertIn(store_id, r['store']) # TEST list_resources # Execute response = self.geoserver_engine.list_resources() # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result result = response['result'] # Returns list self.assertIsInstance(result, list) # layer listed self.assertIn(store_id, result) # TEST get_resources # Execute # Geoserver uses the store_id as the layer/resource name (not the filename) resource_id_name = '{}:{}'.format(workspace, store_id) response = self.geoserver_engine.get_resource(resource_id=resource_id_name) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) # Properties self.assertIn('name', r) self.assertEquals(store_id, r['name']) self.assertIn(store_id, r['wfs']['shapefile']) # TEST delete_resource # Execute # This case the resource id is the same as the store id. response = self.geoserver_engine.delete_resource(resource_id=resource_id_name, store_id=store_id) # Validate response object self.assert_valid_response_object(response) # Success # TODO: delete_resource is returning a 403 error: not authorized. # self.assertTrue(response['success']) def test_create_shapefile_resource_zip(self): # call methods: create_shapefile_resource, list_layers, get_layer, delete_layer # TEST create_shapefile_resource # Test1.zip # Setup shapefile_zip = os.path.join(self.files_root, 'shapefile', "test1.zip") shapefile = "test1" workspace = self.workspace_name store_id = random_string_generator(10) store_id_name = '{}:{}'.format(workspace, store_id) # Execute response = self.geoserver_engine.create_shapefile_resource(store_id=store_id_name, shapefile_zip=shapefile_zip, overwrite=True) # Validate response object self.assert_valid_response_object(response) # Should succeed self.assertTrue(response['success']) # Extract Result r = response['result'] # Type filename = os.path.splitext(os.path.basename(shapefile_zip))[0] self.assertIsInstance(r, dict) self.assertIn(filename, r['name']) self.assertIn(store_id, r['store']) # TEST list_layers test # Execute response = self.geoserver_engine.list_layers() # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result result = response['result'] # Returns list self.assertIsInstance(result, list) # Get the last item from result layer_id = '{}:{}'.format(workspace, shapefile) # TEST get layers test # Execute response = self.geoserver_engine.get_layer(layer_id=layer_id, store_id=store_id) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) self.assertIn(filename, r['name']) self.assertIn(self.workspace_name, r['name']) # TEST delete_layer self.geoserver_engine.delete_layer(layer_id=layer_id, store_id=store_id) self.assert_valid_response_object(response) self.assertTrue(response['success']) def test_create_shapefile_resource_upload(self): # call methods: create_shapefile_resource, list_stores, get_store, delete_store # TEST create_shapefile_resource # Use in memory file list: test.shp and friends # Setup shapefile_cst = os.path.join(self.files_root, 'shapefile', 'test.cst') shapefile_dbf = os.path.join(self.files_root, 'shapefile', 'test.dbf') shapefile_prj = os.path.join(self.files_root, 'shapefile', 'test.prj') shapefile_shp = os.path.join(self.files_root, 'shapefile', 'test.shp') shapefile_shx = os.path.join(self.files_root, 'shapefile', 'test.shx') # Workspace is given store_rand = random_string_generator(10) store_id = '{}:{}'.format(self.workspace_name, store_rand) with open(shapefile_cst, 'rb') as cst_upload,\ open(shapefile_dbf, 'rb') as dbf_upload,\ open(shapefile_prj, 'rb') as prj_upload,\ open(shapefile_shp, 'rb') as shp_upload,\ open(shapefile_shx, 'rb') as shx_upload: upload_list = [cst_upload, dbf_upload, prj_upload, shp_upload, shx_upload] response = self.geoserver_engine.create_shapefile_resource(store_id=store_id, shapefile_upload=upload_list, overwrite=True) # Should succeed self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) self.assertIn(store_rand, r['name']) self.assertIn(store_rand, r['store']) # TEST list_stores # Execute response = self.geoserver_engine.list_stores() # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result result = response['result'] # layer group listed self.assertIn(store_rand, result) # TEST get store # Execute response = self.geoserver_engine.get_store(store_id=store_id) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) # Properties self.assertIn('name', r) self.assertIn(r['name'], store_rand) self.assertIn('workspace', r) self.assertEqual(self.workspace_name, r['workspace']) # TEST delete_store response = self.geoserver_engine.delete_store(store_id=store_id, purge=True, recurse=True) # Failure Check self.assert_valid_response_object(response) self.assertTrue(response['success']) def test_create_coverage_resource_arcgrid(self): # call methods: create_coverage_resource, list_resources, get_resource, delete_resource # TEST create_coverage_resource # precip30min.zip store_name = random_string_generator(10) expected_store_id = '{}:{}'.format(self.workspace_name, store_name) expected_coverage_type = 'arcgrid' coverage_file_name = 'precip30min.zip' coverage_name = coverage_file_name.split('.')[0] coverage_file = os.path.join(self.files_root, "arc_sample", coverage_file_name) with open(coverage_file, 'rb') as coverage_upload: # Execute response = self.geoserver_engine.create_coverage_resource(store_id=expected_store_id, coverage_type=expected_coverage_type, coverage_upload=coverage_upload, overwrite=True) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) # Values self.assertEqual(coverage_name, r['name']) self.assertEqual(self.workspace_name, r['workspace']) # TEST list_resources # Execute response = self.geoserver_engine.list_resources() # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result result = response['result'] # Returns list self.assertIsInstance(result, list) # layer listed self.assertIn(coverage_name, result) # TEST get_resource # Execute resource_id = '{}:{}'.format(self.workspace_name, coverage_name) response = self.geoserver_engine.get_resource(resource_id=resource_id, store_id=store_name) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] self.assertIn('ArcGrid', r['keywords']) self.assertEqual(coverage_name, r['title']) self.assertEqual('coverage', r['resource_type']) # delete_resource # TODO: delete_resource is returning a 403 error: not authorized. # Execute resource_id = '{}:{}'.format(self.workspace_name, coverage_name) response = self.geoserver_engine.delete_resource(resource_id=resource_id, store_id=store_name) # # Validate response object self.assert_valid_response_object(response) # # Success # self.assertTrue(response['success']) def test_create_coverage_resource_grassgrid(self): # call methods: create_coverage_resource, list_layers, get_layer, delete_layer # TEST create_coverage resource # my_grass.zip store_name = random_string_generator(10) expected_store_id = '{}:{}'.format(self.workspace_name, store_name) expected_coverage_type = 'grassgrid' coverage_file_name = 'my_grass.zip' coverage_name = coverage_file_name.split('.')[0] coverage_file = os.path.join(self.files_root, "grass_ascii", coverage_file_name) # Execute response = self.geoserver_engine.create_coverage_resource(store_id=expected_store_id, coverage_type=expected_coverage_type, coverage_file=coverage_file, overwrite=True) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) # Tests self.assertIn(coverage_name, r['name']) self.assertEqual(self.workspace_name, r['workspace']) # TEST list_layers # Execute response = self.geoserver_engine.list_layers() # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result result = response['result'] # Returns list self.assertIsInstance(result, list) # Check if layer is in list self.assertIn(coverage_name, result) # TEST get_layer # Execute layer_id = '{}:{}'.format(self.workspace_name, coverage_name) response = self.geoserver_engine.get_layer(layer_id=layer_id, store_id=store_name) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) self.assertIn(store_name, r['store']) self.assertIn(self.workspace_name, r['name']) # TEST delete_layer self.geoserver_engine.delete_layer(layer_id=layer_id, store_id=store_name) self.assert_valid_response_object(response) self.assertTrue(response['success']) def test_create_coverage_resource_geotiff(self): # adem.tif # call methods: create_coverage_resource, list_stores, get_store, delete_store # TEST create_coverage_resource store_name = random_string_generator(10) expected_store_id = '{}:{}'.format(self.workspace_name, store_name) expected_coverage_type = 'geotiff' coverage_file_name = 'adem.tif' coverage_name = coverage_file_name.split('.')[0] coverage_file = os.path.join(self.files_root, coverage_file_name) with open(coverage_file, 'rb') as coverage_upload: # Execute response = self.geoserver_engine.create_coverage_resource(store_id=expected_store_id, coverage_type=expected_coverage_type, coverage_upload=coverage_upload, overwrite=True) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) # Values self.assertEqual(coverage_name, r['name']) self.assertEqual(self.workspace_name, r['workspace']) # TEST list_stores # Execute response = self.geoserver_engine.list_stores() # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result result = response['result'] # TEST layer group listed self.assertIn(store_name, result) # TEST get store # Execute response = self.geoserver_engine.get_store(store_id=expected_store_id) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) # Properties self.assertIn('name', r) self.assertIn(r['name'], store_name) self.assertIn('workspace', r) self.assertEqual(self.workspace_name, r['workspace']) # TEST delete_store response = self.geoserver_engine.delete_store(store_id=expected_store_id, purge=True, recurse=True) # Failure Check self.assert_valid_response_object(response) self.assertTrue(response['success']) def test_create_coverage_resource_world_file_tif(self): # pk50095.zip # call methods: create_coverage_resource, list_layers, get_layer, delete_layer # TEST create_coverage resource store_name = random_string_generator(10) expected_store_id = '{}:{}'.format(self.workspace_name, store_name) expected_coverage_type = 'worldimage' coverage_file_name = 'Pk50095.zip' coverage_name = coverage_file_name.split('.')[0] coverage_file = os.path.join(self.files_root, "img_sample", coverage_file_name) # Execute response = self.geoserver_engine.create_coverage_resource(store_id=expected_store_id, coverage_type=expected_coverage_type, coverage_file=coverage_file, overwrite=True) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) # Tests self.assertIn(coverage_name, r['name']) self.assertEqual(self.workspace_name, r['workspace']) # TEST list_layers # Execute response = self.geoserver_engine.list_layers() # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result result = response['result'] # Returns list self.assertIsInstance(result, list) # Check if layer is in list self.assertIn(coverage_name, result) # TEST get_layer # Execute layer_id = '{}:{}'.format(self.workspace_name, coverage_name) response = self.geoserver_engine.get_layer(layer_id=layer_id, store_id=store_name) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) self.assertIn(store_name, r['store']) self.assertIn(self.workspace_name, self.workspace_name) # TEST delete_layer self.geoserver_engine.delete_layer(layer_id=coverage_name, store_id=store_name) self.assert_valid_response_object(response) self.assertTrue(response['success']) def test_create_coverage_resource_upload(self): # DO NOT MOCK # Use in memory file list: precip30min.prj & precip30min.asc # call methods: create_coverage_resource, list_resources, get_resource, delete_resource store_id_name = random_string_generator(10) expected_store_id = '{}:{}'.format(self.workspace_name, store_id_name) expected_coverage_type = 'arcgrid' coverage_file_name = 'precip30min.asc' prj_file_name = 'precip30min.prj' coverage_name = coverage_file_name.split('.')[0] arc_sample = os.path.join(self.files_root, "arc_sample") coverage_file = os.path.join(arc_sample, coverage_file_name) prj_file = os.path.join(arc_sample, prj_file_name) with open(coverage_file, 'rb') as coverage_upload: with open(prj_file, 'rb') as prj_upload: upload_list = [coverage_upload, prj_upload] # Execute response = self.geoserver_engine.create_coverage_resource(store_id=expected_store_id, coverage_type=expected_coverage_type, coverage_upload=upload_list, overwrite=True) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) # Values self.assertEqual(coverage_name, r['name']) self.assertEqual(self.workspace_name, r['workspace']) # TEST list_resources # Execute response = self.geoserver_engine.list_resources() # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result result = response['result'] # Returns list self.assertIsInstance(result, list) # layer listed self.assertIn(coverage_name, result) # TEST get_resources # Execute resource_id = "{}:{}".format(self.workspace_name, coverage_name) response = self.geoserver_engine.get_resource(resource_id=resource_id, store_id=store_id_name) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) # Properties self.assertIn('name', r) self.assertEquals(coverage_name, r['name']) self.assertIn(coverage_name, r['wcs']['arcgrid']) # TEST delete_resource # TODO: delete_resource is returning a 403 error: not authorized. # Execute # This case the resource id is the same as the filename. resource_id = '{}:{}'.format(self.workspace_name, coverage_name) response = self.geoserver_engine.delete_resource(resource_id=resource_id, store_id=store_id_name) # Validate response object self.assert_valid_response_object(response) # Success # self.assertTrue(response['success']) def test_create_layer_group(self): # call methods: create_layer_group, list_layer_groups, get_layer_group, delete_layer_group # create_layer_group # Use existing layers and styles in geoserver: # layers: sf:roads, sf:bugsites, sf:streams; # styles: simple_roads, capitals, simple_streams # TEST create_layer_group # Do create # expected_layer_group_id = '{}:{}'.format(self.workspace_name, random_string_generator(10)) expected_layer_group_id = random_string_generator(10) expected_layers = ['roads', 'bugsites', 'streams'] expected_styles = ['simple_roads', 'capitals', 'simple_streams'] # TODO: create_layer_group: fails on catalog.save() when workspace is given. response = self.geoserver_engine.create_layer_group(layer_group_id=expected_layer_group_id, layers=expected_layers, styles=expected_styles) # Should succeed self.assert_valid_response_object(response) self.assertTrue(response['success']) # Validate result = response['result'] self.assertEquals(result['name'], expected_layer_group_id) self.assertEquals(result['layers'], expected_layers) self.assertEquals(result['styles'], expected_styles) # TEST list_layer_groups # Execute response = self.geoserver_engine.list_layer_groups() # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result result = response['result'] # layer group listed self.assertIn(expected_layer_group_id, result) # TEST get layer_group # Execute response = self.geoserver_engine.get_layer_group(layer_group_id=expected_layer_group_id) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) # List of dictionaries self.assertIn('workspace', r) self.assertEqual(None, r['workspace']) self.assertIn('layers', r) self.assertEqual(expected_layers, r['layers']) self.assertIn('styles', r) self.assertEqual(expected_styles, r['styles']) self.assertNotIn('dom', r) # TEST delete layer group # Clean up self.geoserver_engine.delete_layer_group(layer_group_id=expected_layer_group_id) self.assert_valid_response_object(response) self.assertTrue(response['success']) # self.assertIsNone(response['result']) def test_create_workspace(self): # call methods: create_workspace, list_workspaces, get_workspace, delete_workspace # TEST create workspace expected_workspace_id = random_string_generator(10) expected_uri = 'http://www.tethysplatform.org/{}'.format(expected_workspace_id) # create workspace test response = self.geoserver_engine.create_workspace(workspace_id=expected_workspace_id, uri=expected_uri) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) self.assertIn('name', r) self.assertEqual(expected_workspace_id, r['name']) # TEST list workspace # Execute response = self.geoserver_engine.list_workspaces() # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result result = response['result'] # TEST layer group listed self.assertIn(expected_workspace_id, result) # TEST get_workspace # Execute response = self.geoserver_engine.get_workspace(workspace_id=expected_workspace_id) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) # Properties self.assertIn('name', r) self.assertIn(r['name'], expected_workspace_id) # TEST delete work_space # Do delete response = self.geoserver_engine.delete_workspace(workspace_id=expected_workspace_id) # Should succeed self.assert_valid_response_object(response) self.assertTrue(response['success']) self.assertIsNone(response['result']) def test_create_style(self): # call methods: create_style, list_styles, get_style, delete_style # TEST create_style expected_style_id_name = random_string_generator(10) expected_style_id = '{}:{}'.format(self.workspace_name, expected_style_id_name) style_file_name = 'point.sld' expected_sld = os.path.join(self.files_root, style_file_name) # Execute with open(expected_sld, 'r') as sld_file: sld_string = sld_file.read() # TODO: create_style: Fails on when overwrite is False. response = self.geoserver_engine.create_style(style_id=expected_style_id, sld=sld_string, overwrite=True) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) # TEST list_styles # Execute response = self.geoserver_engine.list_styles(workspace=self.workspace_name) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result result = response['result'] # Returns list self.assertIsInstance(result, list) # TEST layer listed self.assertIn(expected_style_id_name, result) # TEST get_style # Execute response = self.geoserver_engine.get_style(style_id=expected_style_id) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) # Properties self.assertIn('name', r) self.assertIn(r['name'], expected_style_id) self.assertIn('workspace', r) self.assertEqual(self.workspace_name, r['workspace']) # TEST delete_style # Do delete response = self.geoserver_engine.delete_style(style_id=expected_style_id) # Should succeed self.assert_valid_response_object(response) self.assertTrue(response['success']) self.assertIsNone(response['result']) def test_link_and_add_table(self): # call methods: link_sqlalchemy_db_to_geoserver, add_table_to_postgis_store, list_stores, get_store, # delete_store self.setup_postgis_table() # TEST link_sqlalchemy_db_to_geoserver store_id_name = random_string_generator(10) store_id = '{}:{}'.format(self.workspace_name, store_id_name) sqlalchemy_engine = create_engine(self.pg_url) response = self.geoserver_engine.link_sqlalchemy_db_to_geoserver(store_id=store_id, sqlalchemy_engine=sqlalchemy_engine, docker=True) # Check for success response self.assertTrue(response['success']) sqlalchemy_engine.dispose() # TEST add_table_to_postgis_store # Execute response = self.geoserver_engine.add_table_to_postgis_store(store_id=store_id, table=self.pg_table_name) # Check for success response self.assertTrue(response['success']) # TEST list_stores # Execute response = self.geoserver_engine.list_stores() # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result result = response['result'] # layer group listed self.assertIn(store_id_name, result) # TEST get store # Execute response = self.geoserver_engine.get_store(store_id=store_id) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) # Properties self.assertIn('name', r) self.assertIn(store_id_name, r['name']) self.assertIn('workspace', r) self.assertEqual(self.workspace_name, r['workspace']) # TEST delete_store response = self.geoserver_engine.delete_store(store_id=store_id, purge=True, recurse=True) # Failure Check self.assert_valid_response_object(response) self.assertTrue(response['success']) def test_create_postgis_feature_resource(self): # call methods: create_postgis_feature_resource (with table), list_stores, get_store, delete_store self.setup_postgis_table() # TEST create_postgis_feature_resource (with table) store_id_name = random_string_generator(10) store_id = '{}:{}'.format(self.workspace_name, store_id_name) response = self.geoserver_engine.create_postgis_feature_resource(store_id=store_id, host=self.pg_host, port=self.pg_port, database=self.pg_database, user=self.pg_username, password=self.pg_password, table=self.pg_table_name) self.assertTrue(response['success']) # TEST list_stores # Execute response = self.geoserver_engine.list_stores() # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result result = response['result'] # layer group listed self.assertIn(store_id_name, result) # TEST get store # Execute response = self.geoserver_engine.get_store(store_id=store_id) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) # Properties self.assertIn('name', r) self.assertIn(store_id_name, r['name']) self.assertIn('workspace', r) self.assertEqual(self.workspace_name, r['workspace']) # TEST delete_store response = self.geoserver_engine.delete_store(store_id=store_id, purge=True, recurse=True) # Failure Check self.assert_valid_response_object(response) self.assertTrue(response['success']) def test_create_sql_view(self): # call methods: create_sql_view, list_resources, list_stores, list_layers self.setup_postgis_table() # TEST create_postgis_feature_resource (with table) store_id_name = random_string_generator(10) store_id = '{}:{}'.format(self.workspace_name, store_id_name) response = self.geoserver_engine.create_postgis_feature_resource(store_id=store_id, host=self.pg_host, port=self.pg_port, database=self.pg_database, user=self.pg_username, password=self.pg_password, table=self.pg_table_name) self.assertTrue(response['success']) feature_type_name = random_string_generator(10) postgis_store_id = '{}:{}'.format(self.workspace_name, store_id_name) sql = "SELECT * FROM {}".format(self.pg_table_name) geometry_column = self.geometry_column geometry_type = self.geometry_type response = self.geoserver_engine.create_sql_view(feature_type_name=feature_type_name, postgis_store_id=postgis_store_id, sql=sql, geometry_column=geometry_column, geometry_type=geometry_type) self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) self.assertIn('name', r) self.assertIn(feature_type_name, r['name']) # TEST list_resources # Execute response = self.geoserver_engine.list_resources() # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result result = response['result'] # Returns list self.assertIsInstance(result, list) # layer listed self.assertIn(feature_type_name, result) # TEST get_resources # Execute # Geoserver uses the store_id as the layer/resource name (not the filename) resource_id_name = '{}:{}'.format(self.workspace_name, feature_type_name) response = self.geoserver_engine.get_resource(resource_id=resource_id_name) # Validate response object self.assert_valid_response_object(response) # Success self.assertTrue(response['success']) # Extract Result r = response['result'] # Type self.assertIsInstance(r, dict) # Properties self.assertIn('name', r) self.assertEquals(feature_type_name, r['name']) self.assertIn(feature_type_name, r['wfs']['shapefile']) # TEST delete_resource # Execute # This case the resource id is the same as the store id. response = self.geoserver_engine.delete_resource(resource_id=resource_id_name, store_id=store_id_name) # Validate response object self.assert_valid_response_object(response)
def setup_join(new_table_owner, table_name, layer_typename, table_attribute_name, layer_attribute_name): LOGGER.info('setup_join') """ Setup the Table Join in GeoNode """ assert isinstance(new_table_owner, User), "new_table_owner must be a User object" assert table_name is not None, "table_name cannot be None" assert layer_typename is not None, "layer_typename cannot be None" assert table_attribute_name is not None, "table_attribute_name cannot be None" assert layer_attribute_name is not None, "layer_attribute_name cannot be None" LOGGER.info('setup_join. Step (1): Retrieve the DataTable object') try: dt = DataTable.objects.get(table_name=table_name) except DataTable.DoesNotExist: err_msg = 'No DataTable object found for table_name "%s"' % table_name LOGGER.error(err_msg) return None, err_msg LOGGER.info('setup_join. Step (2): Retrieve the Layer object') try: layer = Layer.objects.get(typename=layer_typename) except Layer.DoesNotExist: err_msg = 'No Layer object found for layer_typename "%s"' % layer_typename LOGGER.error(err_msg) return None, err_msg LOGGER.info('setup_join. Step (3): Retrieve the DataTableAttribute object') try: table_attribute = DataTableAttribute.objects.get(\ datatable=dt, attribute=table_attribute_name) except DataTableAttribute.DoesNotExist: err_msg = 'No DataTableAttribute object found for table/attribute (%s/%s)' \ % (dt, table_attribute_name) LOGGER.error(err_msg) return None, err_msg LOGGER.info('setup_join. Step (4): Retrieve the LayerAttribute object') try: layer_attribute = LayerAttribute.objects.get(\ layer=layer, attribute=layer_attribute_name) except LayerAttribute.DoesNotExist: err_msg = 'No LayerAttribute object found for layer/attribute (%s/%s)'\ % (layer, layer_attribute_name) LOGGER.error(err_msg) return None, err_msg LOGGER.info('setup_join. Step (5): Build SQL statement to create view') layer_name = layer.typename.split(':')[1] # ------------------------------------------------------------------ # (5) Check if the layer and the table are in the same store (database) # ------------------------------------------------------------------ if layer.store != dt.tablespace: err_msg = 'layer (%s) and tablespace (%s) must be in the same database.'\ % (layer.store, dt.tablespace) LOGGER.error(err_msg) return None, err_msg # ------------------------------------------------------------------ # (5a) Check if the join columns compatible # ------------------------------------------------------------------ column_checker = ColumnChecker(\ layer_name, layer_attribute.attribute, dt.table_name, table_attribute.attribute) (are_cols_compatible, err_msg) = column_checker.are_join_columns_compatible() if not are_cols_compatible: # Doesn't look good, return an error message return None, err_msg # ------------------------------------------------------------------ # (5b) Create SQL statement for the tablejoin # ------------------------------------------------------------------ view_name = get_unique_viewname(dt.table_name, layer_name) # SQL to create the view view_sql = ('CREATE VIEW {0}' ' AS SELECT {1}.{2}, {3}.*' ' FROM {1} INNER JOIN {3}' ' ON {1}."{4}" = {3}."{5}";'.format(\ view_name, # 0 layer_name, # 1 THE_GEOM_LAYER_COLUMN, # 2 dt.table_name, # 3 layer_attribute.attribute, # 4 table_attribute.attribute)) # 5 # Materialized view for next version of Postgres """view_sql = ('create materialized view {0} as' ' select {1}.the_geom, {2}.*' ' from {1} inner join {2}' ' on {1}."{3}" = {2}."{4}";').format(\ view_name, layer_name, dt.table_name, layer_attribute.attribute, table_attribute.attribute) """ LOGGER.info('setup_join. Step (6): Retrieve stats') # ------------------------------------------------------------------ # Retrieve stats # ------------------------------------------------------------------ matched_count_sql = ('select count({0}) from {1} where {1}.{0}' ' in (select "{2}" from {3});').format(\ table_attribute.attribute, dt.table_name, layer_attribute.attribute, layer_name) unmatched_count_sql = ('select count({0}) from {1} where {1}.{0}' ' not in (select "{2}" from {3});').format(\ table_attribute.attribute, dt.table_name, layer_attribute.attribute, layer_name) unmatched_list_sql = ('select {0} from {1} where {1}.{0}' ' not in (select "{2}" from {3}) limit 500;').format(\ table_attribute.attribute, dt.table_name, layer_attribute.attribute, layer_name) # ------------------------------------------------------------------ # Create a TableJoin object # ------------------------------------------------------------------ LOGGER.info('setup_join. Step (7): Create a TableJoin object') tj, created = TableJoin.objects.get_or_create(\ source_layer=layer, datatable=dt, table_attribute=table_attribute, layer_attribute=layer_attribute, view_name=view_name, view_sql=view_sql) tj.save() msgt('table join created! :) %s' % tj.id) # ------------------------------------------------------------------ # Create the View (and double view) # ------------------------------------------------------------------ LOGGER.info('setup_join. Step (8): Create the View (and double view)') # Convenience method to drop a view # drop_view_by_name(view_name) try: conn = psycopg2.connect(get_datastore_connection_string()) cur = conn.cursor() # Create the new view # msg('view_sql: %s' % view_sql) cur.execute(view_sql) #cur.execute(double_view_sql) # For later version of postgres # Record the counts for matched records and # add unmatched records to the TableJoin object # Unmatched count cur.execute(matched_count_sql) tj.matched_records_count = cur.fetchone()[0] # Matched count cur.execute(unmatched_count_sql) tj.unmatched_records_count = int(cur.fetchone()[0]) # Unmatched records list if tj.unmatched_records_count > 0: cur.execute(unmatched_list_sql) tj.unmatched_records_list = ",".join( ['%s' % r[0] for r in cur.fetchall()]) conn.commit() cur.close() # If no records match, then delete the TableJoin # if tj.matched_records_count == 0: # Delete the table join tj.delete() # Create an error message, log it, and send it back err_msg = ('No records matched. Make sure that you chose' ' the correct column and that the chosen layer' ' is in the same geographic area.') LOGGER.error(err_msg) return None, err_msg except Exception as ex_obj: tj.delete() # If needed for debugging, don't delete the table join traceback.print_exc(sys.exc_info()) err_msg = "Error Joining table %s to layer %s: %s" % (\ table_name, layer_typename, str(ex_obj[0])) LOGGER.error(err_msg) if err_msg.find('You might need to add explicit type casts.') > -1: user_msg = "The chosen column is a different data type than the one expected." else: user_msg = err_msg return None, user_msg finally: conn.close() #-------------------------------------------------- # Create the Layer in GeoServer from the view #-------------------------------------------------- LOGGER.info( 'setup_join. Step (9): Create the Layer in GeoServer from the view') try: LOGGER.info('setup_join. Step (9a): Find the datastore') #---------------------------- # Find the datastore #---------------------------- cat = Catalog( settings.GEOSERVER_BASE_URL + "rest", settings.GEOSERVER_CREDENTIALS[0], settings.GEOSERVER_CREDENTIALS[1]) # "admin", "geoserver") workspace = cat.get_workspace('geonode') ds_list = cat.get_xml(workspace.datastore_url) datastores = [ datastore_from_index(cat, workspace, n) for n in ds_list.findall("dataStore") ] ds = None # Iterate through datastores # for datastore in datastores: #msg ('datastore name:', datastore.name) if datastore.name == layer.store: ds = datastore if ds is None: tj.delete() err_msg = "Datastore name not found: '%s' (join)" % settings.DB_DATASTORE_NAME LOGGER.error(str(ds)) return None, err_msg # Publish the feature # LOGGER.info('setup_join. Step (9b): Publish the feature type') ft = cat.publish_featuretype(view_name, ds, layer.srs, srs=layer.srs) #ft = cat.publish_featuretype(double_view_name, ds, layer.srs, srs=layer.srs) LOGGER.info('setup_join. Step (9c): Save the feature type') cat.save(ft) except Exception as e: tj.delete() traceback.print_exc(sys.exc_info()) err_msg = "Error creating GeoServer layer for %s: %s" % (view_name, str(e)) LOGGER.error(err_msg) return None, err_msg # ------------------------------------------------------ # Set the Layer's default Style # ------------------------------------------------------ sld_success, err_msg = set_style_for_new_join_layer(cat, ft, layer) if not sld_success: return None, err_msg # ------------------------------------------------------------------ # Create the Layer in GeoNode from the GeoServer Layer # ------------------------------------------------------------------ LOGGER.info( 'setup_join. Step (10): Create the Layer in GeoNode from the GeoServer Layer' ) try: layer_params = { "workspace": workspace.name, "store": ds.name, "storeType": ds.resource_type, "typename": "%s:%s" % (workspace.name.encode('utf-8'), ft.name.encode('utf-8')), "title": dt.title or 'No title provided', "abstract": dt.abstract or 'No abstract provided', "uuid": str(uuid.uuid4()), "owner": new_table_owner, #"bbox_x0": Decimal(ft.latlon_bbox[0]), #"bbox_x1": Decimal(ft.latlon_bbox[1]), #"bbox_y0": Decimal(ft.latlon_bbox[2]), #"bbox_y1": Decimal(ft.latlon_bbox[3]) } layer, created = Layer.objects.get_or_create(name=view_name, defaults=layer_params) # Set default permissions (public) layer.set_default_permissions() #set_attributes(layer, overwrite=True) tj.join_layer = layer tj.save() except Exception as e: tj.delete() traceback.print_exc(sys.exc_info()) err_msg = "Error creating GeoNode layer for %s: %s" % (view_name, str(e)) LOGGER.error(err_msg) return None, err_msg # ------------------------------------------------------------------ # Create LayerAttributes for the new Layer (not done in GeoNode 2.x) # ------------------------------------------------------------------ LOGGER.info( 'setup_join. Step (11): Create Layer Attributes from the Datatable') (attributes_created, err_msg) = create_layer_attributes_from_datatable(dt, layer) if not attributes_created: LOGGER.error(err_msg) tj.delete() # Delete the table join object return None, "Sorry there was an error creating the Datatable (s11)" return tj, ""
gn_to_gs_fix(layer, res, args.dry_run, creds, args.disable_ssl_verification) except Inconsistency as e: logger.debug("Inconsistency found : %s" % e) errors.append(e) # Layer groups TODO: not managed yet by gsconfig # lgroups = gscatalog.get_layergroups() # for lg in lgroups: # gn_to_gs_fix(lg, args.dry_run, creds) # Workspace elif args.mode == "workspace": if args.item is None: print("Missing item option") parser.print_help() sys.exit() print_banner(args) workspace = gscatalog.get_workspace(name=args.item) if workspace is None: logger.error("workspace \"%s\" not found" % args.item) sys.exit() else: resources = gscatalog.get_resources(workspace=workspace) for res in resources: try: layer = gscatalog.get_layer(res.workspace.name + ":" + res.name) gn_to_gs_fix(layer, res, args.dry_run, creds, args.disable_ssl_verification) except Inconsistency as e: errors.append(e) # Single layer else: # TODO: weird ... gsconfig.get_layer(name="...") returns always a layer, even if it does not exist ... # better off parsing every resources available ? What if the GS has a huge catalog ?
from geoserver.catalog import Catalog import geoserver.util cat = Catalog("http://localhost:9090/geoserver/rest/") cat.username = "******" cat.password = "******" workspace = cat.get_workspace("fenix") cat.create_coveragestore( "test_gsconfig2", "/home/vortex/Desktop/LAYERS/MOROCCO_MICHELA/to_publish/original/wheat_mask.tif", workspace) layer = cat.get_layer("test_gsconfig2") layer._set_default_style("mask") cat.save(layer) # print cat # print "here" # layer = cat.get_style("burg")
class CatalogTests(unittest.TestCase): def setUp(self): self.cat = Catalog(GSPARAMS['GSURL'], username=GSPARAMS['GSUSER'], password=GSPARAMS['GSPASSWORD']) self.gs_version = self.cat.get_short_version() def testGSVersion(self): version = self.cat.get_version() pat = re.compile('\d\.\d+') self.assertTrue(pat.match('2.2.x')) self.assertTrue(pat.match('2.3.2')) self.assertTrue(pat.match('2.3-SNAPSHOT')) self.assertTrue(pat.match(version)) def testWorkspaces(self): self.assertEqual(7, len(self.cat.get_workspaces())) # marking out test since geoserver default workspace is not consistent # self.assertEqual("cite", self.cat.get_default_workspace().name) self.assertEqual("topp", self.cat.get_workspaces(names="topp")[-1].name) self.assertEqual(2, len(self.cat.get_workspaces(names=['topp', 'sde']))) self.assertEqual(2, len(self.cat.get_workspaces(names='topp, sde'))) self.assertEqual("topp", self.cat.get_workspace("topp").name) self.assertIsNone(self.cat.get_workspace("blahblah-")) def testStores(self): self.assertEqual(0, len(self.cat.get_stores(names="nonexistentstore"))) topp = self.cat.get_workspaces("topp")[0] sf = self.cat.get_workspaces("sf")[0] self.assertEqual(9, len(self.cat.get_stores())) self.assertEqual(2, len(self.cat.get_stores(workspaces=topp))) self.assertEqual(2, len(self.cat.get_stores(workspaces=sf))) self.assertEqual(2, len(self.cat.get_stores(workspaces='sf'))) self.assertEqual( 2, len(self.cat.get_stores(names='states_shapefile, sfdem'))) self.assertEqual( 2, len(self.cat.get_stores(names=['states_shapefile', 'sfdem']))) self.assertEqual( "states_shapefile", self.cat.get_stores(names="states_shapefile", workspaces=topp.name)[0].name) self.assertEqual("states_shapefile", self.cat.get_stores(names="states_shapefile")[0].name) self.assertEqual( "sfdem", self.cat.get_stores(names="sfdem", workspaces=sf.name)[0].name) self.assertEqual("sfdem", self.cat.get_store("sfdem", workspace="sf").name) self.assertIsNone(self.cat.get_store("blah+blah-")) def testResources(self): topp = self.cat.get_workspaces("topp")[0] sf = self.cat.get_workspaces("sf")[0] states = self.cat.get_stores(names="states_shapefile", workspaces=topp.name)[0] sfdem = self.cat.get_stores(names="sfdem", workspaces=sf.name)[0] self.assertEqual(19, len(self.cat.get_resources())) self.assertEqual( 2, len( self.cat.get_resources(stores=[states.name, sfdem.name], workspaces=[topp.name, sf.name]))) self.assertEqual( 11, len(self.cat.get_resources(workspaces=[topp.name, sf.name]))) self.assertEqual( "states", self.cat.get_resources(names="states", stores=states.name, workspaces=topp.name)[0].name) self.assertEqual( "states", self.cat.get_resources(names="states", workspaces=topp.name)[0].name) self.assertEqual( "states", self.cat.get_resource("states", workspace=topp.name).name) self.assertIsNone(self.cat.get_resource("blah+1blah-2")) states = self.cat.get_resources(names="states", workspaces=topp.name)[0] fields = [ states.title, states.abstract, states.native_bbox, states.latlon_bbox, states.projection, states.projection_policy ] self.assertFalse(None in fields, str(fields)) self.assertFalse(len(states.keywords) == 0) self.assertFalse(len(states.attributes) == 0) self.assertTrue(states.enabled) self.assertEqual( "sfdem", self.cat.get_resources(names="sfdem", stores=sfdem.name, workspaces=sf.name)[0].name) self.assertEqual( "sfdem", self.cat.get_resources(names="sfdem", workspaces=sf.name)[0].name) def testResourcesUpdate(self): res_dest = self.cat.get_resources() count = 0 for rd in res_dest: # only wms layers if rd.resource_type != "wmsLayer": continue # looking for same name ro = self.cat.get_resources(names=rd.name) if ro is not None: rd.title = ro.title rd.abstract = ro.abstract rd.keywords = ro.keywords rd.projection = ro.projection rd.native_bbox = ro.native_bbox rd.latlon_bbox = ro.latlon_bbox rd.projection_policy = ro.projection_policy rd.enabled = ro.enabled rd.advertised = ro.advertised rd.metadata_links = ro.metadata_links or None self.cat.save(rd) self.cat.reload() count += 1 def testLayers(self): if self.gs_version >= "2.13": expected = set([ 'sf:roads', 'sf:sfdem', 'nurc:mosaic', 'tiger:giant_polygon', 'sf:bugsites', 'topp:states', 'sf:streams', 'tiger:poly_landmarks', 'tiger:poi', 'topp:tasmania_water_bodies', 'tiger:tiger_roads', 'topp:tasmania_roads', 'nurc:Pk50095', 'topp:tasmania_cities', 'nurc:Img_Sample', 'sf:restricted', 'nurc:Arc_Sample', 'sf:archsites', 'topp:tasmania_state_boundaries' ]) else: expected = set([ "Arc_Sample", "Pk50095", "Img_Sample", "mosaic", "sfdem", "bugsites", "restricted", "streams", "archsites", "roads", "tasmania_roads", "tasmania_water_bodies", "tasmania_state_boundaries", "tasmania_cities", "states", "poly_landmarks", "tiger_roads", "poi", "giant_polygon" ]) actual = set(l.name for l in self.cat.get_layers()) missing = expected - actual extras = actual - expected message = "Actual layer list did not match expected! (Extras: %s) (Missing: %s)" % ( extras, missing) self.assert_(len(expected ^ actual) == 0, message) states = self.cat.get_layer("states") self.assert_("states", states.name) self.assert_(isinstance(states.resource, ResourceInfo)) self.assertEqual(set(s.name for s in states.styles), set(['pophatch', 'polygon'])) self.assertEqual(states.default_style.name, "population") def testLayerGroups(self): expected = set(["tasmania", "tiger-ny", "spearfish"]) actual = set(l.name for l in self.cat.get_layergroups( names=["tasmania", "tiger-ny", "spearfish"])) missing = expected - actual extras = actual - expected message = "Actual layergroup list did not match expected! (Extras: %s) (Missing: %s)" % ( extras, missing) self.assert_(len(expected ^ actual) == 0, message) tas = self.cat.get_layergroups(names="tasmania")[0] self.assert_("tasmania", tas.name) self.assert_(isinstance(tas, LayerGroup)) if self.gs_version >= "2.13": self.assertEqual(tas.layers, [ 'topp:tasmania_state_boundaries', 'topp:tasmania_water_bodies', 'topp:tasmania_roads', 'topp:tasmania_cities' ], tas.layers) else: self.assertEqual(tas.layers, [ 'tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities' ], tas.layers) self.assertEqual(tas.styles, [None, None, None, None], tas.styles) # Try to create a new Layer Group into the "topp" workspace self.assert_(self.cat.get_workspaces("topp")[0] is not None) tas2 = self.cat.create_layergroup("tasmania_reloaded", tas.layers, workspace="topp") self.cat.save(tas2) self.assertEqual( 1, len( self.cat.get_layergroups(names='tasmania_reloaded', workspaces="topp"))) tas2 = self.cat.get_layergroups(names='tasmania_reloaded', workspaces="topp")[0] self.assert_("tasmania_reloaded", tas2.name) self.assert_(isinstance(tas2, LayerGroup)) self.assertEqual(tas2.workspace, "topp", tas2.workspace) if self.gs_version >= "2.13": self.assertEqual(tas2.layers, [ 'topp:tasmania_state_boundaries', 'topp:tasmania_water_bodies', 'topp:tasmania_roads', 'topp:tasmania_cities' ], tas2.layers) else: self.assertEqual(tas2.layers, [ 'tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities' ], tas2.layers) self.assertEqual(tas2.styles, [None, None, None, None], tas2.styles) def testStyles(self): self.assertEqual("population", self.cat.get_styles("population")[0].name) self.assertEqual("popshade.sld", self.cat.get_styles("population")[0].filename) self.assertEqual("population", self.cat.get_styles("population")[0].sld_name) self.assertEqual("population", self.cat.get_style("population").sld_name) self.assertIsNone(self.cat.get_style("blah+#5blah-")) self.assertEqual(0, len(self.cat.get_styles('non-existing-style'))) def testEscaping(self): # GSConfig is inconsistent about using exceptions vs. returning None # when a resource isn't found. # But the basic idea is that none of them should throw HTTP errors from # misconstructed URLS self.cat.get_styles("best style ever") self.cat.get_workspaces("best workspace ever") self.assertEqual( 0, len( self.cat.get_stores(workspaces="best workspace ever", names="best store ever"))) self.cat.get_layer("best layer ever") self.cat.get_layergroups("best layergroup ever") def testUnicodeUrl(self): """ Tests that the geoserver.support.url function support unicode strings. """ # Test the url function with unicode seg = [ 'workspaces', 'test', 'datastores', u'operaci\xf3n_repo', 'featuretypes.xml' ] u = build_url(base=self.cat.service_url, seg=seg) self.assertEqual( u, self.cat.service_url + "/workspaces/test/datastores/operaci%C3%B3n_repo/featuretypes.xml") # Test the url function with normal string seg = [ 'workspaces', 'test', 'datastores', 'test-repo', 'featuretypes.xml' ] u = build_url(base=self.cat.service_url, seg=seg) self.assertEqual( u, self.cat.service_url + "/workspaces/test/datastores/test-repo/featuretypes.xml")
#!/usr/bin/env python from geoserver.catalog import Catalog cat = Catalog("http://localhost:8080/geoserver/rest", "admin", "geoserver") native_bbox = \ ['589434.856', '4914006.338', '609527.21', '4928063.398', 'EPSG:26713'] latlon_bbox = ['-103.877', '44.371', '-103.622', '44.5', 'EPSG:4326'] sf = cat.get_workspace('sf') for rs in cat.get_resources(workspace=sf): rs.native_bbox = native_bbox rs.latlon_bbox = latlon_bbox cat.save(rs)
def gs_slurp(self, ignore_errors=True, verbosity=1, console=None, owner=None, workspace=None): """Configure the layers available in GeoServer in GeoNode. It returns a list of dictionaries with the name of the layer, the result of the operation and the errors and traceback if it failed. """ if console is None: console = open(os.devnull, 'w') if verbosity > 1: print >> console, "Inspecting the available layers in GeoServer ..." url = "%srest" % settings.GEOSERVER_BASE_URL cat = Catalog(url, _user, _password) if workspace is not None: workspace = cat.get_workspace(workspace) resources = cat.get_resources(workspace=workspace) number = len(resources) if verbosity > 1: msg = "Found %d layers, starting processing" % number print >> console, msg output = [] for i, resource in enumerate(resources): name = resource.name store = resource.store workspace = store.workspace try: # Avoid circular import problem from geonode.layers.models import Layer layer, created = Layer.objects.get_or_create(name=name, defaults = { "workspace": workspace.name, "store": store.name, "storeType": store.resource_type, "typename": "%s:%s" % (workspace.name, resource.name), "title": resource.title or 'No title provided', "abstract": resource.abstract or 'No abstract provided', "owner": owner, "uuid": str(uuid.uuid4()) }) layer.save() except Exception, e: if ignore_errors: status = 'failed' exception_type, error, traceback = sys.exc_info() else: if verbosity > 0: msg = "Stopping process because --ignore-errors was not set and an error was found." print >> sys.stderr, msg raise Exception('Failed to process %s' % resource.name, e), None, sys.exc_info()[2] else: if created: layer.set_default_permissions() status = 'created' else: status = 'updated' msg = "[%s] Layer %s (%d/%d)" % (status, name, i+1, number) info = {'name': name, 'status': status} if status == 'failed': info['traceback'] = traceback info['exception_type'] = exception_type info['error'] = error output.append(info) if verbosity > 0: print >> console, msg
class GsConn: def __init__(self, host, login, password, debug=False): """ Geoserver connection """ self.host = host self.login = login self.password = password self.debug = debug # Connect to server self.cat = Catalog("http://%s/geoserver/rest" % host, login, password) if self.debug is True: print "Connected to geoserver" def crate_workspace(self, name, overwrite=False): """ Creates a workspace :param name: Workspace name. :param overwrite: If True, delete existing workspace. :return: None """ workspaces = [workspace.name for workspace in self.cat.get_workspaces()] if name in workspaces and overwrite is True: # ws2del = self.cat.get_workspace(name) # self.cat.delete(ws2del, purge=True, recurse=True) return None # NOTE: If we delete the workspace then all associated layers are lost. elif name in workspaces and overwrite is False: print "ERROR: Workspace %s already exists (use overwrite=True)." % name self.cat.create_workspace(name, "http://%s/%s" % (self.host, name)) if self.debug is True: print "Workspace %s available." % name ws = self.cat.get_workspace(name) ws.enabled = True def create_pg_store(self, name, workspace, host, port, login, password, dbname, schema, overwrite=False): """ Creates datastore. :param name: Name of the datastore. :param workspace: Name of the workspace to use. :param overwrite: If True replace datastore. :return: None """ stores = [store.name for store in self.cat.get_stores()] if name in stores and overwrite is True: # st2del = self.cat.get_store(name) # self.cat.delete(st2del, purge=True, recurse=True) # self.cat.reload() return None # NOTE: If we delete store, every layers associated with are lost. elif name in stores and overwrite is False: print "ERROR: Store %s already exists (use overwrite=True)." % name ds = self.cat.create_datastore(name, workspace) ds.connection_parameters.update( host=host, port=port, user=login, passwd=password, dbtype="postgis", database=dbname, schema=schema ) self.cat.save(ds) ds = self.cat.get_store(name) if ds.enabled is False: print "ERROR: Geoserver store %s not enabled" % name if self.debug is True: print "Datastore %s created." % name def publish_pg_layer(self, layer_table, layer_name, store, srid, overwrite=True): """ """ existing_lyr = self.cat.get_layer("ma_carte:%s" % layer_table) if existing_lyr is not None: print "Layer ma_carte:%s already exists, deleting it." % layer_table self.cat.delete(existing_lyr) self.cat.reload() ds = self.cat.get_store(store) ft = self.cat.publish_featuretype(layer_table, ds, "EPSG:%s" % srid, srs="EPSG:4326") ft.projection_policy = "REPROJECT_TO_DECLARED" ft.title = layer_name self.cat.save(ft) if ft.enabled is False: print "ERROR: Layer %s %s %s is not enabled."(ft.workspace.name, ft.store.name, ft.title) if self.debug is True: print "Layer %s>%s>%s published." % (ft.workspace.name, ft.store.name, ft.title) def create_style_from_sld(self, style_name, sld_file, workspace, overwrite=True): """ """ if self.cat.get_style(style_name) is not None: print "Style %s already exists, deleting it." % style_name style2del = self.cat.get_style(style_name) self.cat.delete(style2del) self.cat.create_style( style_name, open(sld_file).read(), overwrite=overwrite ) # FIXME: if ", workspace=workspace" specified can't delete style if self.debug is True: print "Style %s created in Geoserver" % style_name def apply_style_to_layer(self, layer_name, style_name): """ Apply a geoserver styler to a layer """ gs_layer = self.cat.get_layer(layer_name) gs_style = self.cat.get_style(style_name) # FIXME: Which works better? # gs_layer.default_style = gs_style / gs_layer._set_default_style(gs_style) # FIXME: Maybe indicate workspace when saving style then name the style as "workspace:style" gs_layer._set_default_style(gs_style) self.cat.save(gs_layer) if self.debug is True: print "Style applied to %s" % layer_name
#!/usr/bin/env python """ gsconfig is a python library for manipulating a GeoServer instance via the GeoServer RESTConfig API. The project is distributed under a MIT License . """ __author__ = "David Winslow" __copyright__ = "Copyright 2012-2015 Boundless, Copyright 2010-2012 OpenPlans" __license__ = "MIT" from geoserver.catalog import Catalog cat = Catalog("http://localhost:8080/geoserver/rest", "admin", "geoserver") ws = cat.get_workspace("sf") resources = cat.get_resources(workspace=ws) if len(resources) != 0: assert all(r.projection == "EPSG:27613" for r in resources), ws.name
class CatalogTests(unittest.TestCase): def setUp(self): self.cat = Catalog("http://localhost:8080/geoserver/rest") def testAbout(self): about_html = self.cat.about() self.assertTrue('<html xmlns="http://www.w3.org/1999/xhtml"' in about_html) def testGSVersion(self): version = self.cat.gsversion() pat = re.compile('\d\.\d(\.[\dx]|-SNAPSHOT)') self.assertTrue(pat.match('2.2.x')) self.assertTrue(pat.match('2.3.2')) self.assertTrue(pat.match('2.3-SNAPSHOT')) self.assertFalse(pat.match('2.3.y')) self.assertFalse(pat.match('233')) self.assertTrue(pat.match(version)) def testWorkspaces(self): self.assertEqual(7, len(self.cat.get_workspaces())) # marking out test since geoserver default workspace is not consistent # self.assertEqual("cite", self.cat.get_default_workspace().name) self.assertEqual("topp", self.cat.get_workspace("topp").name) def testStores(self): topp = self.cat.get_workspace("topp") sf = self.cat.get_workspace("sf") self.assertEqual(9, len(self.cat.get_stores())) self.assertEqual(2, len(self.cat.get_stores(topp))) self.assertEqual(2, len(self.cat.get_stores(sf))) self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile", topp).name) self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name) self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name) self.assertEqual("sfdem", self.cat.get_store("sfdem", sf).name) self.assertEqual("sfdem", self.cat.get_store("sfdem").name) def testResources(self): topp = self.cat.get_workspace("topp") sf = self.cat.get_workspace("sf") states = self.cat.get_store("states_shapefile", topp) sfdem = self.cat.get_store("sfdem", sf) self.assertEqual(19, len(self.cat.get_resources())) self.assertEqual(1, len(self.cat.get_resources(states))) self.assertEqual(5, len(self.cat.get_resources(workspace=topp))) self.assertEqual(1, len(self.cat.get_resources(sfdem))) self.assertEqual(6, len(self.cat.get_resources(workspace=sf))) self.assertEqual("states", self.cat.get_resource("states", states).name) self.assertEqual("states", self.cat.get_resource("states", workspace=topp).name) self.assertEqual("states", self.cat.get_resource("states").name) states = self.cat.get_resource("states") fields = [ states.title, states.abstract, states.native_bbox, states.latlon_bbox, states.projection, states.projection_policy ] self.assertFalse(None in fields, str(fields)) self.assertFalse(len(states.keywords) == 0) self.assertFalse(len(states.attributes) == 0) self.assertTrue(states.enabled) self.assertEqual("sfdem", self.cat.get_resource("sfdem", sfdem).name) self.assertEqual("sfdem", self.cat.get_resource("sfdem", workspace=sf).name) self.assertEqual("sfdem", self.cat.get_resource("sfdem").name) def testLayers(self): expected = set(["Arc_Sample", "Pk50095", "Img_Sample", "mosaic", "sfdem", "bugsites", "restricted", "streams", "archsites", "roads", "tasmania_roads", "tasmania_water_bodies", "tasmania_state_boundaries", "tasmania_cities", "states", "poly_landmarks", "tiger_roads", "poi", "giant_polygon" ]) actual = set(l.name for l in self.cat.get_layers()) missing = expected - actual extras = actual - expected message = "Actual layer list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing) self.assert_(len(expected ^ actual) == 0, message) states = self.cat.get_layer("states") self.assert_("states", states.name) self.assert_(isinstance(states.resource, ResourceInfo)) self.assertEqual(set(s.name for s in states.styles), set(['pophatch', 'polygon'])) self.assertEqual(states.default_style.name, "population") def testLayerGroups(self): expected = set(["tasmania", "tiger-ny", "spearfish"]) actual = set(l.name for l in self.cat.get_layergroups()) missing = expected - actual extras = actual - expected message = "Actual layergroup list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing) self.assert_(len(expected ^ actual) == 0, message) tas = self.cat.get_layergroup("tasmania") self.assert_("tasmania", tas.name) self.assert_(isinstance(tas, LayerGroup)) self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers) self.assertEqual(tas.styles, [None, None, None, None], tas.styles) def testStyles(self): self.assertEqual(20, len(self.cat.get_styles())) self.assertEqual("population", self.cat.get_style("population").name) self.assertEqual("popshade.sld", self.cat.get_style("population").filename) self.assertEqual("population", self.cat.get_style("population").sld_name) def testEscaping(self): # GSConfig is inconsistent about using exceptions vs. returning None # when a resource isn't found. # But the basic idea is that none of them should throw HTTP errors from # misconstructed URLS self.cat.get_style("best style ever") self.cat.get_workspace("best workspace ever") self.cat.get_store(workspace="best workspace ever", name="best store ever") self.assertRaises(FailedRequestError, lambda: self.cat.get_resource( workspace="best workspace ever", store="best store ever", name="best resource ever")) self.cat.get_layer("best layer ever") self.cat.get_layergroup("best layergroup ever") def testUnicodeUrl(self): """ Tests that the geoserver.support.url function support unicode strings. """ # Test the url function with unicode seg = ['workspaces', 'test', 'datastores', u'operaci\xf3n_repo', 'featuretypes.xml'] u = url(base=self.cat.service_url, seg=seg) self.assertEqual(u, self.cat.service_url + "/workspaces/test/datastores/operaci%C3%B3n_repo/featuretypes.xml") # Test the url function with normal string seg = ['workspaces', 'test', 'datastores', 'test-repo', 'featuretypes.xml'] u = url(base=self.cat.service_url, seg=seg) self.assertEqual(u, self.cat.service_url + "/workspaces/test/datastores/test-repo/featuretypes.xml")
class UploaderTests(TestCase): """Basic checks to make sure pages load, etc. """ def create_datastore(self, connection, catalog): """Convenience method for creating a datastore. """ settings = connection.settings_dict ds_name = settings['NAME'] params = { 'database': ds_name, 'passwd': settings['PASSWORD'], 'namespace': 'http://www.geonode.org/', 'type': 'PostGIS', 'dbtype': 'postgis', 'host': settings['HOST'], 'user': settings['USER'], 'port': settings['PORT'], 'enabled': 'True' } store = catalog.create_datastore(ds_name, workspace=self.workspace) store.connection_parameters.update(params) try: catalog.save(store) except FailedRequestError: # assuming this is because it already exists pass return catalog.get_store(ds_name) def create_user(self, username, password, **kwargs): """Convenience method for creating users. """ user, created = User.objects.get_or_create(username=username, **kwargs) if created: user.set_password(password) user.save() return user def setUp(self): self.assertTrue( os.path.exists(_TEST_FILES_DIR), 'Test could not run due to missing test data at {0!r}'.format( _TEST_FILES_DIR)) # These tests require geonode to be running on :80! self.postgis = db.connections['datastore'] self.postgis_settings = self.postgis.settings_dict self.admin_user = self.create_user('admin', 'admin', is_superuser=True) self.non_admin_user = self.create_user('non_admin', 'non_admin') self.catalog = Catalog(ogc_server_settings.internal_rest, *ogc_server_settings.credentials) if self.catalog.get_workspace('geonode') is None: self.catalog.create_workspace('geonode', 'http://www.geonode.org/') self.workspace = 'geonode' self.datastore = self.create_datastore(self.postgis, self.catalog) def tearDown(self): """Clean up geoserver. """ self.catalog.delete(self.datastore, recurse=True) def import_file(self, path, configs=None): """Imports the file. """ if configs is None: configs = [] self.assertTrue(os.path.exists(path)) # run ogr2ogr ogr = OGRImport(path) layers = ogr.handle(configuration_options=configs) return layers def generic_import(self, filename, configs=None): if configs is None: configs = [{'index': 0}] path = test_file(filename) results = self.import_file(path, configs=configs) layer_results = [] for result in results: if result[1].get('raster'): layer_path = result[0] layer_name = os.path.splitext(os.path.basename(layer_path))[0] layer = Layer.objects.get(name=layer_name) self.assertTrue(layer_path.endswith('.tif')) self.assertTrue(os.path.exists(layer_path)) gdal_layer = gdal.OpenEx(layer_path) self.assertTrue(gdal_layer.GetDriver().ShortName, 'GTiff') layer_results.append(layer) else: layer = Layer.objects.get(name=result[0]) self.assertEqual(layer.srid, 'EPSG:4326') self.assertEqual(layer.store, self.datastore.name) self.assertEqual(layer.storeType, 'dataStore') if not path.endswith('zip'): self.assertGreaterEqual(layer.attributes.count(), DataSource(path)[0].num_fields) layer_results.append(layer) return layer_results[0] def generic_api_upload(self, filenames, configs=None): """Tests the import api. """ client = AdminClient() client.login_as_non_admin() # Don't accidentally iterate over given 'foo' as ['f', 'o', 'o']. self.assertNotIsInstance(filenames, str) # Upload Files outfiles = [] for filename in filenames: path = test_file(filename) with open(path) as stream: data = stream.read() upload = SimpleUploadedFile(filename, data) outfiles.append(upload) response = client.post(reverse('uploads-new-json'), { 'file': outfiles, 'json': json.dumps(configs) }, follow=True) content = json.loads(response.content) self.assertEqual(response.status_code, 200) self.assertEqual(content['id'], 1) # Configure Uploaded Files upload_id = content['id'] upload_layers = UploadLayer.objects.filter(upload_id=upload_id) for upload_layer in upload_layers: for config in configs: if config['upload_file_name'] == os.path.basename( upload_layer.name): payload = config['config'] url = '/importer-api/data-layers/{0}/configure/'.format( upload_layer.id) response = client.post(url, data=json.dumps(payload), content_type='application/json') self.assertEqual(response.status_code, 200) url = '/importer-api/data-layers/{0}/'.format( upload_layer.id) response = client.get(url, content_type='application/json') self.assertEqual(response.status_code, 200) return content def generic_raster_import(self, filename, configs=None): if configs is None: configs = [{'index': 0}] path = test_file(filename) results = self.import_file(path, configs=configs) layer_path = results[0][0] layer_name = os.path.splitext(os.path.basename(layer_path))[0] layer = Layer.objects.get(name=layer_name) self.assertTrue(layer_path.endswith('.tif')) self.assertTrue(os.path.exists(layer_path)) gdal_layer = gdal.OpenEx(layer_path) self.assertTrue(gdal_layer.GetDriver().ShortName, 'GTiff') return layer def test_multi_upload(self): """Tests Uploading Multiple Files """ # Number of layers in each file upload_layer_counts = [1, 1, 1] upload = self.generic_api_upload(filenames=[ 'boxes_with_year_field.zip', 'boxes_with_date.zip', 'point_with_date.geojson' ], configs=[{ 'upload_file_name': 'boxes_with_year_field.shp', 'config': [{ 'index': 0 }] }, { 'upload_file_name': 'boxes_with_date.shp', 'config': [{ 'index': 0 }] }, { 'upload_file_name': 'point_with_date.geojson', 'config': [{ 'index': 0 }] }]) self.assertEqual(Layer.objects.count(), sum(upload_layer_counts)) self.assertEqual(9, upload['count']) def test_upload_with_slds(self): """Tests Uploading sld """ upload = self.generic_api_upload( filenames=['boxes_with_date.zip', 'boxes.sld', 'boxes1.sld'], configs=[{ 'upload_file_name': 'boxes_with_date.shp', 'config': [{ 'index': 0, 'default_style': 'boxes.sld', 'styles': ['boxes.sld', 'boxes1.sld'] }] }]) self.assertEqual(6, upload['count']) upload_id = upload['id'] uplayers = UploadLayer.objects.filter(upload=upload_id) layer_id = uplayers[0].pk upfiles_count = UploadFile.objects.filter(upload=upload_id).count() self.assertEqual(6, upfiles_count) # Warning: this assumes that Layer pks equal UploadLayer pks layer = Layer.objects.get(pk=layer_id) gslayer = self.catalog.get_layer(layer.name) default_style = gslayer.default_style # TODO: can we use public API or omit this? self.catalog._cache.clear() self.assertEqual('boxes.sld', default_style.filename) def test_upload_with_metadata(self): """Tests Uploading metadata """ upload = self.generic_api_upload(filenames=[ 'boxes_with_date.zip', 'samplemetadata.xml', ], configs=[{ 'upload_file_name': 'boxes_with_date.shp', 'config': [{ 'index': 0, 'metadata': 'samplemetadata.xml' }] }]) self.assertEqual(5, upload['count']) upload_id = upload['id'] uplayers = UploadLayer.objects.filter(upload=upload_id) layer_id = uplayers[0].pk upfiles_count = UploadFile.objects.filter(upload=upload_id).count() self.assertEqual(5, upfiles_count) layer = Layer.objects.get(pk=layer_id) self.assertEqual(layer.language, 'eng') self.assertEqual(layer.title, 'Old_Americas_LSIB_Polygons_Detailed_2013Mar') def test_geotiff_raster(self): """Exercise GeoTIFF raster import. """ layer = self.generic_raster_import('test_grid.tif', configs=[{ 'index': 0 }]) self.assertTrue(layer.name.startswith('test_grid')) def test_nitf_raster(self): """Tests NITF raster import """ layer = self.generic_raster_import('test_nitf.nitf') self.assertTrue(layer.name.startswith('test_nitf')) def test_box_with_year_field(self): """Tests the import of test_box_with_year_field. """ layer = self.generic_import('boxes_with_year_field.shp', configs=[{ 'index': 0, 'convert_to_date': ['date'] }]) date_attr = get_layer_attr(layer, 'date_as_date') self.assertEqual(date_attr.attribute_type, 'xsd:dateTime') configure_time( self.catalog.get_layer(layer.name).resource, attribute=date_attr.attribute, ) self.generic_time_check(layer, attribute=date_attr.attribute) def test_boxes_with_date(self): """Tests the import of test_boxes_with_date. """ layer = self.generic_import('boxes_with_date.shp', configs=[{ 'index': 0, 'convert_to_date': ['date'], 'start_date': 'date', 'configureTime': True }]) date_attr = get_layer_attr(layer, 'date_as_date') self.assertEqual(date_attr.attribute_type, 'xsd:dateTime') configure_time( self.catalog.get_layer(layer.name).resource, attribute=date_attr.attribute, ) self.generic_time_check(layer, attribute=date_attr.attribute) def test_boxes_with_date_gpkg(self): """Tests the import of test_boxes_with_date.gpkg. """ layer = self.generic_import('boxes_with_date.gpkg', configs=[{ 'index': 0, 'convert_to_date': ['date'], 'start_date': 'date', 'configureTime': True }]) date_attr = get_layer_attr(layer, 'date_as_date') self.assertEqual(date_attr.attribute_type, 'xsd:dateTime') configure_time( self.catalog.get_layer(layer.name).resource, attribute=date_attr.attribute, ) self.generic_time_check(layer, attribute=date_attr.attribute) def test_boxes_plus_raster_gpkg_by_index(self): """ Tests the import of multilayer vector + tile geopackage using index, treating tile layers as rasters. Tile layers are now treated by default as a distinct layer type. This test forces them to still be treated as rasters and should be removed once tests for vector/tile geopackage files are in place. """ layer = self.generic_import('boxes_plus_raster.gpkg', configs=[ { 'index': 0, 'convert_to_date': ['date'], 'start_date': 'date', 'configureTime': True }, { 'index': 1 }, { 'index': 2 }, { 'index': 3 }, { 'index': 4 }, { 'index': 5 }, { 'index': 6, 'layer_type': 'raster' }, { 'index': 7, 'layer_type': 'raster' }, ]) date_attr = get_layer_attr(layer, 'date_as_date') self.assertEqual(date_attr.attribute_type, 'xsd:dateTime') configure_time( self.catalog.get_layer(layer.name).resource, attribute=date_attr.attribute, ) self.generic_time_check(layer, attribute=date_attr.attribute) def test_boxes_with_date_csv(self): """Tests a CSV with WKT polygon. """ layer = self.generic_import('boxes_with_date.csv', configs=[{ 'index': 0, 'convert_to_date': ['date'] }]) date_attr = get_layer_attr(layer, 'date_as_date') self.assertEqual(date_attr.attribute_type, 'xsd:dateTime') configure_time( self.catalog.get_layer(layer.name).resource, attribute=date_attr.attribute, ) self.generic_time_check(layer, attribute=date_attr.attribute) def test_csv_missing_features(self): """Test csv that has some rows without geoms and uses ISO-8859 (Latin 4) encoding. """ self.generic_import('missing-features.csv', configs=[{'index': 0}]) def test_boxes_with_iso_date(self): """Tests the import of test_boxes_with_iso_date. """ layer = self.generic_import('boxes_with_date_iso_date.shp', configs=[{ 'index': 0, 'convert_to_date': ['date'] }]) date_attr = get_layer_attr(layer, 'date_as_date') self.assertEqual(date_attr.attribute_type, 'xsd:dateTime') configure_time( self.catalog.get_layer(layer.name).resource, attribute=date_attr.attribute, ) self.generic_time_check(layer, attribute=date_attr.attribute) def test_duplicate_imports(self): """Import the same layer twice to ensure file names increment properly. """ path = test_file('boxes_with_date_iso_date.zip') ogr = OGRImport(path) layers1 = ogr.handle({'index': 0, 'name': 'test'}) layers2 = ogr.handle({'index': 0, 'name': 'test'}) self.assertEqual(layers1[0][0], 'test') self.assertEqual(layers2[0][0], 'test0') def test_launder(self): """Ensure the launder function works as expected. """ self.assertEqual(launder('tm_world_borders_simpl_0.3'), 'tm_world_borders_simpl_0_3') self.assertEqual(launder('Testing#'), 'testing_') self.assertEqual(launder(' '), '_') def test_boxes_with_date_iso_date_zip(self): """Tests the import of test_boxes_with_iso_date. """ layer = self.generic_import('boxes_with_date_iso_date.zip', configs=[{ 'index': 0, 'convert_to_date': ['date'] }]) date_attr = get_layer_attr(layer, 'date_as_date') self.assertEqual(date_attr.attribute_type, 'xsd:dateTime') configure_time( self.catalog.get_layer(layer.name).resource, attribute=date_attr.attribute, ) self.generic_time_check(layer, attribute=date_attr.attribute) def test_boxes_with_dates_bc(self): """Tests the import of test_boxes_with_dates_bc. """ layer = self.generic_import('boxes_with_dates_bc.shp', configs=[{ 'index': 0, 'convert_to_date': ['date'] }]) date_attr = get_layer_attr(layer, 'date_as_date') self.assertEqual(date_attr.attribute_type, 'xsd:dateTime') configure_time( self.catalog.get_layer(layer.name).resource, attribute=date_attr.attribute, ) self.generic_time_check(layer, attribute=date_attr.attribute) def test_point_with_date(self): """Tests the import of point_with_date.geojson """ layer = self.generic_import('point_with_date.geojson', configs=[{ 'index': 0, 'convert_to_date': ['date'] }]) # OGR will name geojson layers 'ogrgeojson' we rename to the path basename self.assertTrue(layer.name.startswith('point_with_date')) date_attr = get_layer_attr(layer, 'date_as_date') self.assertEqual(date_attr.attribute_type, 'xsd:dateTime') configure_time( self.catalog.get_layer(layer.name).resource, attribute=date_attr.attribute, ) self.generic_time_check(layer, attribute=date_attr.attribute) def test_boxes_with_end_date(self): """Tests the import of test_boxes_with_end_date. This layer has a date and an end date field that are typed correctly. """ layer = self.generic_import('boxes_with_end_date.shp', configs=[{ 'index': 0, 'convert_to_date': ['date', 'enddate'], 'start_date': 'date', 'end_date': 'enddate', 'configureTime': True }]) date_attr = get_layer_attr(layer, 'date_as_date') end_date_attr = get_layer_attr(layer, 'enddate_as_date') self.assertEqual(date_attr.attribute_type, 'xsd:dateTime') self.assertEqual(end_date_attr.attribute_type, 'xsd:dateTime') configure_time(self.catalog.get_layer(layer.name).resource, attribute=date_attr.attribute, end_attribute=end_date_attr.attribute) self.generic_time_check(layer, attribute=date_attr.attribute, end_attribute=end_date_attr.attribute) def test_us_states_kml(self): """Tests the import of us_states_kml. This layer has a date and an end date field that are typed correctly. """ # TODO: Support time in kmls. layer = self.generic_import('us_states.kml', configs=[{'index': 0}]) self.assertEqual(layer.name.lower(), "us_states") def test_mojstrovka_gpx(self): """Tests the import of mojstrovka.gpx. This layer has a date and an end date field that are typed correctly. """ layer = self.generic_import('mojstrovka.gpx', configs=[{ 'index': 0, 'convert_to_date': ['time'], 'configureTime': True }]) date_attr = get_layer_attr(layer, 'time_as_date') self.assertEqual(date_attr.attribute_type, u'xsd:dateTime') configure_time(self.catalog.get_layer(layer.name).resource, attribute=date_attr.attribute) self.generic_time_check(layer, attribute=date_attr.attribute) def generic_time_check(self, layer, attribute=None, end_attribute=None): """Convenience method to run generic tests on time layers. """ # TODO: can we use public API or omit this? self.catalog._cache.clear() resource = self.catalog.get_resource(layer.name, store=layer.store, workspace=self.workspace) time_info = resource.metadata['time'] self.assertEqual('LIST', time_info.presentation) self.assertEqual(True, time_info.enabled) self.assertEqual(attribute, time_info.attribute) self.assertEqual(end_attribute, time_info.end_attribute) def test_us_shootings_csv(self): """Tests the import of US_Shootings.csv. """ if osgeo.gdal.__version__ < '2.0.0': self.skipTest('GDAL Version does not support open options') path = test_file('US_Shootings.csv') layer = self.generic_import(path, configs=[{ 'index': 0, 'convert_to_date': ['Date'] }]) self.assertTrue(layer.name.startswith('us_shootings')) date_field = 'date' configure_time(self.catalog.get_layer(layer.name).resource, attribute=date_field) self.generic_time_check(layer, attribute=date_field) def test_sitins(self): """Tests the import of US_Civil_Rights_Sitins0.csv """ if osgeo.gdal.__version__ < '2.0.0': self.skipTest('GDAL Version does not support open options') layer = self.generic_import('US_Civil_Rights_Sitins0.csv', configs=[{ 'index': 0, 'convert_to_date': ['Date'] }]) self.assertEqual(layer.name.lower(), 'us_civil_rights_sitins0') def get_layer_names(self, path): """Gets layer names from a data source. """ data_source = DataSource(path) return [layer.name for layer in data_source] def test_gdal_import(self): path = test_file('point_with_date.geojson') self.generic_import(path, configs=[{ 'index': 0, 'convert_to_date': ['date'] }]) def test_wfs(self): """Tests the import from a WFS Endpoint """ wfs = 'WFS:http://demo.geo-solutions.it/geoserver/tiger/wfs' ogr = OGRImport(wfs) configs = [ { 'layer_name': 'tiger:giant_polygon' }, { 'layer_name': 'tiger:poi' }, ] layers = ogr.handle(configuration_options=configs) for result in layers: layer = Layer.objects.get(name=result[0]) self.assertEqual(layer.srid, 'EPSG:4326') self.assertEqual(layer.store, self.datastore.name) self.assertEqual(layer.storeType, 'dataStore') def test_arcgisjson(self): """Tests the import from a WFS Endpoint """ endpoint = 'http://sampleserver6.arcgisonline.com/arcgis/rest/services/Water_Network/FeatureServer/16/query'\ '?where=objectid=326&outfields=*&f=json' ogr = OGRImport(endpoint) configs = [{'index': 0}] layers = ogr.handle(configuration_options=configs) for result in layers: layer = Layer.objects.get(name=result[0]) self.assertEqual(layer.srid, 'EPSG:4326') self.assertEqual(layer.store, self.datastore.name) self.assertEqual(layer.storeType, 'dataStore') def test_file_add_view(self): """Tests the file_add_view. """ client = AdminClient() # test login required for this view request = client.get(reverse('uploads-new')) self.assertEqual(request.status_code, 302) client.login_as_non_admin() with open(test_file('point_with_date.geojson')) as stream: response = client.post(reverse('uploads-new'), {'file': stream}, follow=True) self.assertEqual(response.status_code, 200) self.assertEqual(response.context['request'].path, reverse('uploads-list')) self.assertEqual(len(response.context['object_list']), 1) upload = response.context['object_list'][0] self.assertEqual(upload.user.username, 'non_admin') self.assertEqual(upload.file_type, 'GeoJSON') self.assertTrue(upload.uploadlayer_set.all()) self.assertEqual(upload.state, 'UPLOADED') self.assertIsNotNone(upload.name) uploaded_file = upload.uploadfile_set.first() self.assertTrue(os.path.exists(uploaded_file.file.path)) with open(test_file('empty_file.geojson')) as stream: response = client.post(reverse('uploads-new'), {'file': stream}, follow=True) self.assertEqual(response.status_code, 200) self.assertIn('file', response.context_data['form'].errors) def test_file_add_view_as_json(self): """Tests the file_add_view. """ client = AdminClient() client.login_as_non_admin() with open(test_file('point_with_date.geojson')) as stream: response = client.post(reverse('uploads-new-json'), {'file': stream}, follow=True) self.assertEqual(response.status_code, 200) self.assertIn('application/json', response.get('Content-Type', '')) content = json.loads(response.content) self.assertIn('state', content) self.assertIn('id', content) def test_describe_fields(self): """Tests the describe fields functionality. """ path = test_file('US_Shootings.csv') with GDALInspector(path) as inspector: layers = inspector.describe_fields() self.assertTrue(layers[0]['layer_name'], 'us_shootings') self.assertEqual([n['name'] for n in layers[0]['fields']], [ 'Date', 'Shooter', 'Killed', 'Wounded', 'Location', 'City', 'Longitude', 'Latitude' ]) self.assertEqual(layers[0]['feature_count'], 203) def test_gdal_file_type(self): """Tests the describe fields functionality. """ filenames = { 'US_Shootings.csv': {'CSV'}, 'point_with_date.geojson': {'GeoJSON'}, 'mojstrovka.gpx': {'GPX'}, 'us_states.kml': {'LIBKML', 'KML'}, 'boxes_with_year_field.shp': {'ESRI Shapefile'}, 'boxes_with_date_iso_date.zip': {'ESRI Shapefile'} } from osgeo_importer.models import NoDataSourceFound try: for filename, file_type in sorted(filenames.items()): path = test_file(filename) with GDALInspector(path) as inspector: self.assertIn(inspector.file_type(), file_type) except NoDataSourceFound: logging.exception('No data source found in: {0}'.format(path)) raise def test_configure_view(self): """Tests the configuration view. """ path = test_file('point_with_date.geojson') new_user = User.objects.create(username='******') new_user_perms = ['change_resourcebase_permissions'] client = AdminClient() client.login_as_non_admin() with open(path) as stream: response = client.post(reverse('uploads-new'), {'file': stream}, follow=True) upload = response.context['object_list'][0] payload = [{ 'index': 0, 'convert_to_date': ['date'], 'start_date': 'date', 'configureTime': True, 'editable': True, 'permissions': { 'users': { 'test': new_user_perms, 'AnonymousUser': [ 'change_layer_data', 'download_resourcebase', 'view_resourcebase' ] } } }] response = client.post( '/importer-api/data-layers/{0}/configure/'.format(upload.id), data=json.dumps(payload), content_type='application/json') self.assertTrue(response.status_code, 200) first_layer = Layer.objects.all()[0] self.assertEqual(first_layer.srid, 'EPSG:4326') self.assertEqual(first_layer.store, self.datastore.name) self.assertEqual(first_layer.storeType, 'dataStore') self.assertTrue(first_layer.attributes[1].attribute_type, 'xsd:dateTime') self.assertEqual(Layer.objects.all()[0].owner.username, self.non_admin_user.username) perms = first_layer.get_all_level_info() user = User.objects.get(username=self.non_admin_user.username) # check user permissions expected_perms = [ u'publish_resourcebase', u'change_resourcebase_permissions', u'delete_resourcebase', u'change_resourcebase', u'change_resourcebase_metadata', u'download_resourcebase', u'view_resourcebase', u'change_layer_style', u'change_layer_data' ] for perm in expected_perms: self.assertIn(perm, perms['users'][user]) self.assertTrue(perms['users'][new_user]) self.assertIn('change_resourcebase_permissions', perms['users'][new_user]) self.assertIn( 'change_layer_data', perms['users'][User.objects.get(username='******')]) catalog_layer = self.catalog.get_layer(first_layer.name) self.assertIn('time', catalog_layer.resource.metadata) self.assertEqual(UploadLayer.objects.first().layer, first_layer) def test_configure_view_convert_date(self): """Tests the configure view with a dataset that needs to be converted to a date. """ client = AdminClient() client.login_as_non_admin() with open(test_file('US_Shootings.csv')) as stream: response = client.post(reverse('uploads-new'), {'file': stream}, follow=True) upload = response.context['object_list'][0] payload = [{ 'index': 0, 'convert_to_date': ['Date'], 'start_date': 'Date', 'configureTime': True, 'editable': True }] response = client.get( '/importer-api/data-layers/{0}/configure/'.format(upload.id)) self.assertEqual(response.status_code, 405) response = client.post( '/importer-api/data-layers/{0}/configure/'.format(upload.id)) self.assertEqual(response.status_code, 400) response = client.post( '/importer-api/data-layers/{0}/configure/'.format(upload.id), data=json.dumps(payload), content_type='application/json') self.assertTrue(response.status_code, 200) first_layer = Layer.objects.all()[0] self.assertEqual(first_layer.srid, 'EPSG:4326') self.assertEqual(first_layer.store, self.datastore.name) self.assertEqual(first_layer.storeType, 'dataStore') self.assertTrue(first_layer.attributes[1].attribute_type, 'xsd:dateTime') self.assertTrue(first_layer.attributes.filter(attribute='date'), 'xsd:dateTime') catalog_layer = self.catalog.get_layer(first_layer.name) self.assertIn('time', catalog_layer.resource.metadata) # ensure a user who does not own the upload cannot configure an import from it. client.logout() client.login_as_admin() response = client.post( '/importer-api/data-layers/{0}/configure/'.format(upload.id)) self.assertEqual(response.status_code, 404) def test_list_api(self): client = AdminClient() response = client.get('/importer-api/data/') self.assertEqual(response.status_code, 401) client.login_as_non_admin() response = client.get('/importer-api/data/') self.assertEqual(response.status_code, 200) admin = User.objects.get(username=self.admin_user.username) non_admin = User.objects.get(username=self.non_admin_user.username) path = test_file('US_Shootings.csv') with open(path, 'rb') as stream: uploaded_file = SimpleUploadedFile('test_data', stream.read()) admin_upload = UploadedData.objects.create(state='Admin test', user=admin) admin_upload.uploadfile_set.add( UploadFile.objects.create(file=uploaded_file)) non_admin_upload = UploadedData.objects.create( state='Non admin test', user=non_admin) non_admin_upload.uploadfile_set.add( UploadFile.objects.create(file=uploaded_file)) client.login_as_admin() response = client.get('/importer-api/data/') self.assertEqual(response.status_code, 200) body = json.loads(response.content) self.assertEqual(len(body['objects']), 2) response = client.get('/importer-api/data/?user__username=admin') self.assertEqual(response.status_code, 200) body = json.loads(response.content) self.assertEqual(len(body['objects']), 1) def test_layer_list_api(self): client = AdminClient() response = client.get('/importer-api/data-layers/') self.assertEqual(response.status_code, 401) client.login_as_non_admin() response = client.get('/importer-api/data-layers/') self.assertEqual(response.status_code, 200) def test_delete_from_non_admin_api(self): """Ensure users can delete their data. """ client = AdminClient() client = AdminClient() client.login_as_non_admin() with open(test_file('point_with_date.geojson')) as stream: response = client.post(reverse('uploads-new'), {'file': stream}, follow=True) self.assertEqual(UploadedData.objects.all().count(), 1) upload_id = UploadedData.objects.first().id response = client.delete('/importer-api/data/{0}/'.format(upload_id)) self.assertEqual(response.status_code, 204) self.assertEqual(UploadedData.objects.all().count(), 0) def test_delete_from_admin_api(self): """Ensure that administrators can delete data that isn't theirs. """ client = AdminClient() client.login_as_non_admin() with open(test_file('point_with_date.geojson')) as stream: response = client.post(reverse('uploads-new'), {'file': stream}, follow=True) self.assertEqual(UploadedData.objects.all().count(), 1) client.logout() client.login_as_admin() upload_id = UploadedData.objects.first().id response = client.delete('/importer-api/data/{0}/'.format(upload_id)) self.assertEqual(response.status_code, 204) self.assertEqual(UploadedData.objects.all().count(), 0) def naming_an_import(self): """Tests providing a name in the configuration options. """ client = AdminClient() client.login_as_non_admin() name = 'point-with-a-date' with open(test_file('point_with_date.geojson')) as stream: response = client.post(reverse('uploads-new'), {'file': stream}, follow=True) payload = { 'index': 0, 'convert_to_date': ['date'], 'start_date': 'date', 'configureTime': True, 'name': name, 'editable': True } response = client.post('/importer-api/data-layers/1/configure/', data=json.dumps(payload), content_type='application/json') self.assertEqual(response.status_code, 200) first_layer = Layer.objects.all()[0] self.assertEqual(first_layer.title, name.replace('-', '_')) def test_api_import(self): """Tests the import api. """ client = AdminClient() client.login_as_non_admin() with open(test_file('point_with_date.geojson')) as stream: response = client.post(reverse('uploads-new'), {'file': stream}, follow=True) payload = { 'index': 0, 'convert_to_date': ['date'], 'start_date': 'date', 'configureTime': True, 'editable': True } self.assertIsInstance( UploadLayer.objects.first().configuration_options, dict) response = client.get('/importer-api/data-layers/1/') self.assertEqual(response.status_code, 200) response = client.post('/importer-api/data-layers/1/configure/', data=json.dumps([payload]), content_type='application/json') self.assertEqual(response.status_code, 200) self.assertIn('task', response.content) first_layer = Layer.objects.all()[0] self.assertEqual(first_layer.srid, 'EPSG:4326') self.assertEqual(first_layer.store, self.datastore.name) self.assertEqual(first_layer.storeType, 'dataStore') self.assertTrue(first_layer.attributes[1].attribute_type, 'xsd:dateTime') catalog_layer = self.catalog.get_layer(first_layer.name) self.assertIn('time', catalog_layer.resource.metadata) self.assertEqual(UploadLayer.objects.first().layer, first_layer) self.assertTrue(UploadLayer.objects.first().task_id) def test_valid_file_extensions(self): """Test the file extension validator. """ for extension in load_handler(OSGEO_IMPORTER, 'test.txt').valid_extensions: filename = 'test.{0}'.format(extension) upload = SimpleUploadedFile(filename, '') self.assertIsNone(validate_file_extension(upload)) with self.assertRaises(ValidationError): validate_file_extension(SimpleUploadedFile('test.txt', '')) def test_no_geom(self): """Test the file extension validator. """ with self.assertRaises(ValidationError): validate_inspector_can_read( SimpleUploadedFile('test.csv', 'test,loc\nyes,POINT(0,0)')) # This should pass (geom type is unknown) validate_inspector_can_read( SimpleUploadedFile('test.csv', 'test,WKT\nyes,POINT(0,0)')) def test_numeric_overflow(self): """Regression test for numeric field overflows in shapefiles. # https://trac.osgeo.org/gdal/ticket/5241 """ self.generic_import('Walmart.zip', configs=[{ 'configureTime': False, 'convert_to_date': ['W1_OPENDAT'], 'editable': True, 'index': 0, 'name': 'Walmart', 'start_date': 'W1_OPENDAT' }]) def test_multipolygon_shapefile(self): """Tests shapefile with multipart polygons. """ self.generic_import('PhoenixFirstDues.zip', configs=[{'index': 0}]) def test_istanbul(self): """Tests shapefile with multipart polygons and non-WGS84 SR. """ result = self.generic_import('Istanbul.zip', configs=[{'index': 0}]) feature_type = self.catalog.get_resource(result.name) self.assertEqual(feature_type.projection, 'EPSG:32635') def test_houston_tx_annexations(self): """Tests Shapefile with originally unsupported EPSG Code. """ result = self.generic_import('HoustonTXAnnexations.zip', configs=[{ 'index': 0 }]) feature_type = self.catalog.get_resource(result.name) self.assertEqual(feature_type.projection, 'EPSG:2278') def test_gwc_handler(self): """Tests the GeoWebCache handler """ layer = self.generic_import('boxes_with_date.shp', configs=[{ 'index': 0, 'convert_to_date': ['date'], 'start_date': 'date', 'configureTime': True }]) gwc = GeoWebCacheHandler(None) gs_layer = self.catalog.get_layer(layer.name) self.assertTrue(gwc.time_enabled(gs_layer)) gs_layer.fetch() payload = self.catalog.http.request(gwc.gwc_url(gs_layer)) self.assertIn('regexParameterFilter', payload[1]) self.assertEqual(int(payload[0]['status']), 200) # Don't configure time, ensure everything still works layer = self.generic_import('boxes_with_date_iso_date.shp', configs=[{ 'index': 0 }]) gs_layer = self.catalog.get_layer(layer.name) self.catalog._cache.clear() gs_layer.fetch() payload = self.catalog.http.request(gwc.gwc_url(gs_layer)) self.assertNotIn('regexParameterFilter', payload[1]) self.assertEqual(int(payload[0]['status']), 200) def test_utf8(self): """Tests utf8 characters in attributes """ path = test_file('china_provinces.shp') layer = self.generic_import(path) ogr = OGRImport(path) datastore, _ = ogr.open_target_datastore(ogr.target_store) sql = ("select NAME_CH from {0} where NAME_PY = 'An Zhou'".format( layer.name)) result = datastore.ExecuteSQL(sql) feature = result.GetFeature(0) self.assertEqual(feature.GetField('name_ch'), '安州') def test_non_converted_date(self): """Test converting a field as date. """ results = self.generic_import('TM_WORLD_BORDERS_2005.zip', configs=[{ 'index': 0, 'start_date': 'Year', 'configureTime': True }]) layer = self.catalog.get_layer(results.typename) self.assertIn('time', layer.resource.metadata) self.assertEqual('year', layer.resource.metadata['time'].attribute) def test_fid_field(self): """ Regression test for preserving an FID field when target layer supports it but source does not. """ self.generic_import('noaa_paleoclimate.zip', configs=[{'index': 0}]) def test_csv_with_wkb_geometry(self): """Exercise import of CSV files with multiple geometries. """ filenames = [ 'police_csv.csv', 'police_csv_nOGC.csv', 'police_csv_noLatLon.csv', 'police_csv_WKR.csv', 'police_csv_nFID.csv', 'police_csv_nOGFID.csv', 'police_csv_noWKB.csv' ] for filename in filenames: self.generic_import( filename, { 'configureTime': True, 'convert_to_date': ['date_time'], 'editable': True, 'index': 0, 'name': filename.lower(), 'permissions': { 'users': { 'AnonymousUser': [ 'change_layer_data', 'download_resourcebase', 'view_resourcebase' ] } }, 'start_date': 'date_time', })
class wrap_geoserver: """ Geoserver (gsconfig) wrapper """ def __init__(self, geoserver_name, username=None, password=None, easy=False): if geoserver_name in list(REST.keys()): self.path = REST[geoserver_name] else: self.path = geoserver_name self.wms = self.path.replace("rest/", "wms") self.name = geoserver_name self.catalog = Catalog(self.path, username, password) if not easy: self.layers = [] self.layer_names = [] for layer in self.catalog.get_layers(): self.layers.append(layer) self.layer_names.append(layer.name) self.stores = [store for store in self.catalog.get_stores()] self.store_names = [store.name for store in self.stores] styles = [] self.workspaces = [] self.workspace_names = [] for workspace in self.catalog.get_workspaces(): styles = styles + self.catalog.get_styles(workspace) self.workspace_names.append(workspace._name) self.workspaces.append(workspace) self.styles = styles + [ style for style in self.catalog.get_styles() ] self.style_names = [style.name for style in self.styles] def unpack(self, workspace_name, store_type="datastore"): layers_and_styles = {} features = [] workspace = self.get_workspace(workspace_name) if store_type == "datastore": store_url = workspace.datastore_url elif store_type == "coveragestore": store_url = workspace.coveragestore_url else: print("No correct store given") for datastore in tqdm(get(store_url, "name")): url = "{}workspaces/{}/datastores/{}".format( self.path, workspace.name, datastore) features = features + get(url, between_quotes=True) for feature in features: layer_name = os.path.basename(feature).split(".")[0] self.get_layer(self.get_slug(workspace.name, layer_name)) layers_and_styles[layer_name] = self.layer.default_style setattr(self, workspace_name + "_data", layers_and_styles) return layers_and_styles def get_layer(self, layer, easy=False): self.layer = self.catalog.get_layer(layer) if not easy: self.resource = self.layer.resource self.layer_name = self.layer.resource.name self.sld_name = self.layer.default_style.name self.sld_body = self.layer.default_style.sld_body self.layer_latlon_bbox = self.layer.resource.latlon_bbox self.layer_title = self.layer.resource.title self.layer_abstract = self.layer.resource.abstract def get_store(self, layer): self.store = self.layer.resource._store def get_resource(self): self.resource = self.catalog.get_resource(self.layer.name, self.store) def get_workspace(self, workspace_name): self.workspace = self.catalog.get_workspace(workspace_name) self.workspace_name = self.workspace._name return self.workspace def write_abstract(self, data, load_resource=True): if load_resource: self.get_resource() self.resource.abstract = data self.catalog.save(self.resource) def write_title(self, title): self.resource.title = title self.catalog.save(self.resource) def get_connection_parameters(self): self.get_resource() return self.resource.store.connection_parameters def create_workspace(self, workspace_name): workspace_exists = workspace_name in self.workspace_names if not workspace_exists: self.workspace = self.catalog.create_workspace(workspace_name) else: print("workspace already exists, using existing workspace") self.workspace = self.catalog.get_workspace(workspace_name) self.workspace_name = workspace_name def create_postgis_datastore(self, store_name, workspace_name, pg_data): try: self.store = self.catalog.get_store(store_name, self.workspace_name) print("store within workspace exists, using existing store") except Exception as e: print(e) ds = self.catalog.create_datastore(store_name, workspace_name) ds.connection_parameters.update( host=pg_data["host"], port=pg_data["port"], database=pg_data["database"], user=pg_data["username"], passwd=pg_data["password"], dbtype="postgis", schema="public", ) self.save(ds) self.store = self.catalog.get_store(store_name, self.workspace_name) self.store_name = store_name def publish_layer(self, layer_name, workspace_name, overwrite=False, epsg="3857", reload=False): layer_exists = layer_name in self.layer_names # if layer_name in self.workspace_layers[workspace_name]: slug = self.get_slug(workspace_name, layer_name) if overwrite and layer_exists: print("Layer exists, deleting layer") try: self.layer = self.catalog.get_layer(slug) self.delete(self.layer) self.reload() layer_exists = False except Exception as e: print(e) print("Layer does not exist in workspace") layer_exists = False if not layer_exists: feature_type = self.catalog.publish_featuretype( layer_name, self.store, "EPSG:{}".format(str(epsg)), srs="EPSG:{}".format(str(epsg)), ) self.save(feature_type) self.feature_type = feature_type else: print("layer already exists, using existing layer") if reload: self.get_layer(slug) self.layer_name = layer_name def publish_layergroup(self, name, layers, styles=(), bounds=None, workspace=None): layer_group = self.catalog.create_layergroup(name, layers, styles, bounds, workspace) self.save(layer_group) def save(self, save_object): return self.catalog.save(save_object) def close(self): self.catalog = None def delete(self, delete_object): self.catalog.delete(delete_object) def reload(self): self.catalog.reload() def upload_shapefile(self, layer_name, shapefile_path): path = shapefile_path.split(".shp")[0] shapefile = shapefile_and_friends(path) ft = self.catalog.create_featurestore(layer_name, shapefile, self.workspace) self.save(ft) def upload_sld(self, sld_name, workspace_name, sld, overwrite=True): style_exists = sld_name in self.style_names if overwrite and style_exists: print("Overwriting style") style = self.catalog.get_style(sld_name, workspace_name) self.delete(style) self.reload() style_exists = False if not style_exists: try: self.catalog.create_style(sld_name, sld, False, workspace_name, "sld11") except Exception as e: print(e) style = self.catalog.get_style(sld_name, workspace_name) self.delete(style) self.reload() self.catalog.create_style(sld_name, sld, False, workspace_name, "sld10") self.style_name = sld_name else: if style_exists: print("Style already exists, using current style") self.style_name = sld_name def set_sld_for_layer(self, workspace_name=None, style_name=None, use_custom=False): if not use_custom: workspace_name = self.workspace_name style_name = self.style_name self.style_slug = self.get_slug(workspace_name, style_name) else: if workspace_name is None: self.style_slug = style_name else: self.style_slug = self.get_slug(workspace_name, style_name) self.style = self.catalog.get_style(self.style_slug) print("Setting {} for {}".format(self.style.name, self.layer.name)) self.layer.default_style = self.style self.save(self.layer) def get_slug(self, workspace, name): return "{}:{}".format(workspace, name) def get_slug_data(self, slug): workspace_name = slug.split(":")[0] layer_name = slug.split(":")[1] return workspace_name, layer_name def get_sld(self, layer_slug=None): if layer_slug is None: self.style = self.catalog.get_style(self.layer_slug) else: self.style = self.catalog.get_style(layer_slug) self.sld_body = self.style.sld_body return self.sld_body def get_layer_workspace(self, layer_name): return self.catalog.get_layer(layer_name).resource.workspace.name
def createDataStore(name, filename, format="shapefile"): cat = Catalog("{0}/rest/".format(geoserver_connection), geoserver_username, geoserver_password) ws = cat.get_workspace(workspace) msg = "" if format == "shapefile": shapefile = shapefile_and_friends(filename) try: cat.create_featurestore(name, shapefile, workspace) except ConflictingDataError as inst: msg = str(inst) except: raise resource = cat.get_resource(name, workspace=ws) resource.projection = 'EPSG:4326' cat.save(resource) resource.projection_policy = 'REPROJECT_TO_DECLARED' cat.save(resource) resource.refresh() bbox = resource.latlon_bbox[:4] solr_geom = 'ENVELOPE({0},{1},{2},{3})'.format(bbox[0], bbox[1], bbox[3], bbox[2]) return { "solr_geom": solr_geom, "msg": msg, "resource_type": resource.resource_type } elif format == "image": if cat.get_store(name): newcs = cat.get_store(name, workspace=ws) msg = "Geoserver datastore already existed. Update existing datastore." else: newcs = cat.create_coveragestore2(name, ws) newcs.type = "GeoTIFF" newcs.url = filename cat.save(newcs) # add coverage url = "{0}/rest/workspaces/{1}/coveragestores/{2}/coverages.json" url = url.format(geoserver_connection, ws.name, name) headers = {"Content-Type": "application/json"} coverageName = os.path.splitext(os.path.basename(filename))[0] postdata = { "coverage": { "nativeCoverageName": coverageName, "name": coverageName, 'projectionPolicy': 'REPROJECT_TO_DECLARED', 'srs': 'EPSG:4326' } } requests.post(url, json.dumps(postdata), headers=headers, auth=(geoserver_username, geoserver_password)) # Reproject resource = cat.get_resource(name, workspace=ws) url = "{0}/rest/workspaces/{1}/coveragestores/{2}/coverages/{2}?{3}" parameters = "recalculate=nativebbox,latlonbbox" url = url.format(geoserver_connection, ws.name, name, parameters) headers = {"Content-Type": "application/x-www-form-urlencoded"} requests.post(url, headers=headers, auth=(geoserver_username, geoserver_password)) # resource.refresh() bbox = resource.latlon_bbox[:4] solr_geom = 'ENVELOPE({0},{1},{2},{3})'.format(bbox[0], bbox[1], bbox[3], bbox[2]) return { "solr_geom": solr_geom, "msg": msg, "resource_type": resource.resource_type } return True
def _register_cascaded_service(url, type, name, username, password, wms=None, owner=None, parent=None): """ Register a service as cascading WMS """ try: service = Service.objects.get(base_url=url) return_dict = {} return_dict['service_id'] = service.pk return_dict['msg'] = "This is an existing Service" return HttpResponse(json.dumps(return_dict), mimetype='application/json', status=200) except: # TODO: Handle this error properly pass if wms is None: wms = WebMapService(url) # TODO: Make sure we are parsing all service level metadata # TODO: Handle for setting ServiceProfiletRole service = Service.objects.create(base_url=url, type=type, method='C', name=name, version=wms.identification.version, title=wms.identification.title, abstract=wms.identification.abstract, online_resource=wms.provider.url, owner=owner, parent=parent) service.keywords = ','.join(wms.identification.keywords) service.save() service.set_default_permissions() if type in ['WMS', 'OWS']: # Register the Service with GeoServer to be cascaded cat = Catalog(settings.OGC_SERVER['default']['LOCATION'] + "rest", _user, _password) cascade_ws = cat.get_workspace(name) if cascade_ws is None: cascade_ws = cat.create_workspace( name, "http://geonode.org/" + name) # TODO: Make sure there isn't an existing store with that name, and # deal with it if there is try: cascade_store = cat.get_store(name, cascade_ws) except: cascade_store = cat.create_wmsstore( name, cascade_ws, username, password) cascade_store.capabilitiesURL = url cascade_store.type = "WMS" cat.save(cascade_store) available_resources = cascade_store.get_resources(available=True) elif type == 'WFS': # Register the Service with GeoServer to be cascaded cat = Catalog(settings.OGC_SERVER['default']['LOCATION'] + "rest", _user, _password) # Can we always assume that it is geonode? cascade_ws = cat.get_workspace(settings.CASCADE_WORKSPACE) if cascade_ws is None: cascade_ws = cat.create_workspace( settings.CASCADE_WORKSPACE, "http://geonode.org/cascade") try: wfs_ds = cat.get_store(name, cascade_ws) except: wfs_ds = cat.create_datastore(name, cascade_ws) connection_params = { "WFSDataStoreFactory:MAXFEATURES": "0", "WFSDataStoreFactory:TRY_GZIP": "true", "WFSDataStoreFactory:PROTOCOL": "false", "WFSDataStoreFactory:LENIENT": "true", "WFSDataStoreFactory:TIMEOUT": "3000", "WFSDataStoreFactory:BUFFER_SIZE": "10", "WFSDataStoreFactory:ENCODING": "UTF-8", "WFSDataStoreFactory:WFS_STRATEGY": "nonstrict", "WFSDataStoreFactory:GET_CAPABILITIES_URL": url, } if username and password: connection_params["WFSDataStoreFactory:USERNAME"] = username connection_params["WFSDataStoreFactory:PASSWORD"] = password wfs_ds.connection_parameters = connection_params cat.save(wfs_ds) available_resources = wfs_ds.get_resources(available=True) # Save the Service record service, created = Service.objects.get_or_create(type=type, method='C', base_url=url, name=name, owner=owner) service.save() service.set_default_permissions() elif type == 'WCS': return HttpResponse('Not Implemented (Yet)', status=501) else: return HttpResponse( 'Invalid Method / Type combo: ' + 'Only Cascaded WMS, WFS and WCS supported', mimetype="text/plain", status=400) message = "Service %s registered" % service.name return_dict = [{'status': 'ok', 'msg': message, 'service_id': service.pk, 'service_name': service.name, 'service_title': service.title, 'available_layers': available_resources }] if settings.USE_QUEUE: # Create a layer import job WebServiceHarvestLayersJob.objects.get_or_create(service=service) else: _register_cascaded_layers(service) return HttpResponse(json.dumps(return_dict), mimetype='application/json', status=200)
class ModifyingTests(unittest.TestCase): def setUp(self): self.cat = Catalog(GSPARAMS['GSURL'], username=GSPARAMS['GSUSER'], password=GSPARAMS['GSPASSWORD']) def testFeatureTypeSave(self): # test saving round trip rs = self.cat.get_resource("bugsites") old_abstract = rs.abstract new_abstract = "Not the original abstract" enabled = rs.enabled # Change abstract on server rs.abstract = new_abstract self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(new_abstract, rs.abstract) self.assertEqual(enabled, rs.enabled) # Change keywords on server rs.keywords = ["bugsites", "gsconfig"] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(["bugsites", "gsconfig"], rs.keywords) self.assertEqual(enabled, rs.enabled) # Change metadata links on server rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual([ ("text/xml", "TC211", "http://example.com/gsconfig.test.metadata") ], rs.metadata_links) self.assertEqual(enabled, rs.enabled) # Restore abstract rs.abstract = old_abstract self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(old_abstract, rs.abstract) def testDataStoreCreate(self): ds = self.cat.create_datastore("vector_gsconfig") ds.connection_parameters.update(**DBPARAMS) self.cat.save(ds) def testPublishFeatureType(self): # Use the other test and store creation to load vector data into a database # @todo maybe load directly to database? try: self.testDataStoreCreateAndThenAlsoImportData() except FailedRequestError: pass try: lyr = self.cat.get_layer('import') # Delete the existing layer and resource to allow republishing. self.cat.delete(lyr) self.cat.delete(lyr.resource) ds = self.cat.get_store("gsconfig_import_test") # make sure it's gone self.assert_(self.cat.get_layer('import') is None) self.cat.publish_featuretype("import", ds, native_crs="EPSG:4326") # and now it's not self.assert_(self.cat.get_layer('import') is not None) finally: # tear stuff down to allow the other test to pass if we run first ds = self.cat.get_store("gsconfig_import_test") lyr = self.cat.get_layer('import') # Delete the existing layer and resource to allow republishing. try: if lyr: self.cat.delete(lyr) self.cat.delete(lyr.resource) if ds: self.cat.delete(ds) except: pass def testDataStoreModify(self): ds = self.cat.get_store("sf") self.assertFalse("foo" in ds.connection_parameters) ds.connection_parameters = ds.connection_parameters ds.connection_parameters["foo"] = "bar" orig_ws = ds.workspace.name self.cat.save(ds) ds = self.cat.get_store("sf") self.assertTrue("foo" in ds.connection_parameters) self.assertEqual("bar", ds.connection_parameters["foo"]) self.assertEqual(orig_ws, ds.workspace.name) @drop_table('import') def testDataStoreCreateAndThenAlsoImportData(self): ds = self.cat.create_datastore("gsconfig_import_test") ds.connection_parameters.update(**DBPARAMS) self.cat.save(ds) ds = self.cat.get_store("gsconfig_import_test") self.cat.add_data_to_store( ds, "import", { 'shp': 'test/data/states.shp', 'shx': 'test/data/states.shx', 'dbf': 'test/data/states.dbf', 'prj': 'test/data/states.prj' }) @drop_table('import2') def testVirtualTables(self): ds = self.cat.create_datastore("gsconfig_import_test2") ds.connection_parameters.update(**DBPARAMS) self.cat.save(ds) ds = self.cat.get_store("gsconfig_import_test2") self.cat.add_data_to_store( ds, "import2", { 'shp': 'test/data/states.shp', 'shx': 'test/data/states.shx', 'dbf': 'test/data/states.dbf', 'prj': 'test/data/states.prj' }) store = self.cat.get_store("gsconfig_import_test2") geom = JDBCVirtualTableGeometry('the_geom', 'MultiPolygon', '4326') ft_name = 'my_jdbc_vt_test' epsg_code = 'EPSG:4326' sql = "select * from import2 where 'STATE_NAME' = 'Illinois'" keyColumn = None parameters = None jdbc_vt = JDBCVirtualTable(ft_name, sql, 'false', geom, keyColumn, parameters) ft = self.cat.publish_featuretype(ft_name, store, epsg_code, jdbc_virtual_table=jdbc_vt) # DISABLED; this test works only in the very particular case # "mytiff.tiff" is already present into the GEOSERVER_DATA_DIR # def testCoverageStoreCreate(self): # ds = self.cat.create_coveragestore2("coverage_gsconfig") # ds.data_url = "file:test/data/mytiff.tiff" # self.cat.save(ds) def testCoverageStoreModify(self): cs = self.cat.get_store("sfdem") self.assertEqual("GeoTIFF", cs.type) cs.type = "WorldImage" self.cat.save(cs) cs = self.cat.get_store("sfdem") self.assertEqual("WorldImage", cs.type) # not sure about order of test runs here, but it might cause problems # for other tests if this layer is misconfigured cs.type = "GeoTIFF" self.cat.save(cs) def testCoverageSave(self): # test saving round trip rs = self.cat.get_resource("Arc_Sample") old_abstract = rs.abstract new_abstract = "Not the original abstract" # # Change abstract on server rs.abstract = new_abstract self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual(new_abstract, rs.abstract) # Restore abstract rs.abstract = old_abstract self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual(old_abstract, rs.abstract) # Change metadata links on server rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual([ ("text/xml", "TC211", "http://example.com/gsconfig.test.metadata") ], rs.metadata_links) self.assertEqual(enabled, rs.enabled) srs_before = set(['EPSG:4326']) srs_after = set(['EPSG:4326', 'EPSG:3785']) formats = set( ['ARCGRID', 'ARCGRID-GZIP', 'GEOTIFF', 'PNG', 'GIF', 'TIFF']) formats_after = set(["PNG", "GIF", "TIFF"]) # set and save request_srs_list self.assertEquals(set(rs.request_srs_list), srs_before, str(rs.request_srs_list)) rs.request_srs_list = rs.request_srs_list + ['EPSG:3785'] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.request_srs_list), srs_after, str(rs.request_srs_list)) # set and save response_srs_list self.assertEquals(set(rs.response_srs_list), srs_before, str(rs.response_srs_list)) rs.response_srs_list = rs.response_srs_list + ['EPSG:3785'] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.response_srs_list), srs_after, str(rs.response_srs_list)) # set and save supported_formats self.assertEquals(set(rs.supported_formats), formats, str(rs.supported_formats)) rs.supported_formats = ["PNG", "GIF", "TIFF"] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.supported_formats), formats_after, str(rs.supported_formats)) def testWmsStoreCreate(self): ws = self.cat.create_wmsstore("wmsstore_gsconfig") ws.capabilitiesURL = "http://suite.opengeo.org/geoserver/ows?service=wms&version=1.1.1&request=GetCapabilities" ws.type = "WMS" self.cat.save(ws) def testWmsLayer(self): self.cat.create_workspace("wmstest", "http://example.com/wmstest") wmstest = self.cat.get_workspace("wmstest") wmsstore = self.cat.create_wmsstore("wmsstore", wmstest) wmsstore.capabilitiesURL = "http://suite.opengeo.org/geoserver/ows?service=wms&version=1.1.1&request=GetCapabilities" wmsstore.type = "WMS" self.cat.save(wmsstore) wmsstore = self.cat.get_store("wmsstore") self.assertEqual(1, len(self.cat.get_stores(wmstest))) available_layers = wmsstore.get_resources(available=True) for layer in available_layers: # sanitize the layer name - validation will fail on newer geoservers name = layer.replace(':', '_') new_layer = self.cat.create_wmslayer(wmstest, wmsstore, name, nativeName=layer) added_layers = wmsstore.get_resources() self.assertEqual(len(available_layers), len(added_layers)) changed_layer = added_layers[0] self.assertEqual(True, changed_layer.advertised) self.assertEqual(True, changed_layer.enabled) changed_layer.advertised = False changed_layer.enabled = False self.cat.save(changed_layer) self.cat._cache.clear() changed_layer = wmsstore.get_resources()[0] changed_layer.fetch() self.assertEqual(False, changed_layer.advertised) self.assertEqual(False, changed_layer.enabled) # Testing projection and projection policy changes changed_layer.projection = "EPSG:900913" changed_layer.projection_policy = "REPROJECT_TO_DECLARED" self.cat.save(changed_layer) self.cat._cache.clear() layer = self.cat.get_layer(changed_layer.name) self.assertEqual(layer.resource.projection_policy, changed_layer.projection_policy) self.assertEqual(layer.resource.projection, changed_layer.projection) def testFeatureTypeCreate(self): shapefile_plus_sidecars = shapefile_and_friends("test/data/states") expected = { 'shp': 'test/data/states.shp', 'shx': 'test/data/states.shx', 'dbf': 'test/data/states.dbf', 'prj': 'test/data/states.prj' } self.assertEqual(len(expected), len(shapefile_plus_sidecars)) for k, v in expected.iteritems(): self.assertEqual(v, shapefile_plus_sidecars[k]) sf = self.cat.get_workspace("sf") self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf) self.assert_( self.cat.get_resource("states_test", workspace=sf) is not None) self.assertRaises( ConflictingDataError, lambda: self.cat.create_featurestore( "states_test", shapefile_plus_sidecars, sf)) self.assertRaises( UploadError, lambda: self.cat.create_coveragestore( "states_raster_test", shapefile_plus_sidecars, sf)) bogus_shp = { 'shp': 'test/data/Pk50095.tif', 'shx': 'test/data/Pk50095.tif', 'dbf': 'test/data/Pk50095.tfw', 'prj': 'test/data/Pk50095.prj' } self.assertRaises( UploadError, lambda: self.cat.create_featurestore("bogus_shp", bogus_shp, sf)) lyr = self.cat.get_layer("states_test") self.cat.delete(lyr) self.assert_(self.cat.get_layer("states_test") is None) def testCoverageCreate(self): tiffdata = { 'tiff': 'test/data/Pk50095.tif', 'tfw': 'test/data/Pk50095.tfw', 'prj': 'test/data/Pk50095.prj' } sf = self.cat.get_workspace("sf") ft = self.cat.create_coveragestore("Pk50095", tiffdata, sf) self.assert_( self.cat.get_resource("Pk50095", workspace=sf) is not None) self.assertRaises( ConflictingDataError, lambda: self.cat.create_coveragestore("Pk50095", tiffdata, sf)) self.assertRaises( UploadError, lambda: self.cat.create_featurestore( "Pk50095_vector", tiffdata, sf)) bogus_tiff = { 'tiff': 'test/data/states.shp', 'tfw': 'test/data/states.shx', 'prj': 'test/data/states.prj' } self.assertRaises( UploadError, lambda: self.cat.create_coveragestore("states_raster", bogus_tiff)) ft_ext = self.cat.create_coveragestore_external_geotiff( "Pk50095_ext", 'file:test/data/Pk50095.tif', sf) def testLayerSave(self): # test saving round trip lyr = self.cat.get_layer("states") old_attribution = lyr.attribution new_attribution = { 'title': 'Not the original attribution', 'width': '123', 'height': '321', 'href': 'http://www.georchestra.org', 'url': 'https://www.cigalsace.org/portail/cigal/documents/page/mentions-legales/Logo_geOrchestra.jpg', 'type': 'image/jpeg' } # change attribution on server lyr.attribution = new_attribution self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(new_attribution, lyr.attribution) # Restore attribution lyr.attribution = old_attribution self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(old_attribution, lyr.attribution) self.assertEqual(lyr.default_style.name, "population") old_default_style = lyr.default_style lyr.default_style = (s for s in lyr.styles if s.name == "pophatch").next() lyr.styles = [old_default_style] self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(lyr.default_style.name, "pophatch") self.assertEqual([s.name for s in lyr.styles], ["population"]) def testStyles(self): # check count before tests (upload) count = len(self.cat.get_styles()) # upload new style, verify existence self.cat.create_style("fred", open("test/fred.sld").read()) fred = self.cat.get_style("fred") self.assert_(fred is not None) self.assertEqual("Fred", fred.sld_title) # replace style, verify changes self.cat.create_style("fred", open("test/ted.sld").read(), overwrite=True) fred = self.cat.get_style("fred") self.assert_(fred is not None) self.assertEqual("Ted", fred.sld_title) # delete style, verify non-existence self.cat.delete(fred, purge=True) self.assert_(self.cat.get_style("fred") is None) # attempt creating new style self.cat.create_style("fred", open("test/fred.sld").read()) fred = self.cat.get_style("fred") self.assertEqual("Fred", fred.sld_title) # verify it can be found via URL and check the name f = self.cat.get_style_by_url(fred.href) self.assert_(f is not None) self.assertEqual(f.name, fred.name) # compare count after upload self.assertEqual(count + 1, len(self.cat.get_styles())) # attempt creating a new style without "title" self.cat.create_style("notitle", open("test/notitle.sld").read()) notitle = self.cat.get_style("notitle") self.assertEqual(None, notitle.sld_title) def testWorkspaceStyles(self): # upload new style, verify existence self.cat.create_style("jed", open("test/fred.sld").read(), workspace="topp") jed = self.cat.get_style("jed", workspace="blarny") self.assert_(jed is None) jed = self.cat.get_style("jed", workspace="topp") self.assert_(jed is not None) self.assertEqual("Fred", jed.sld_title) jed = self.cat.get_style("topp:jed") self.assert_(jed is not None) self.assertEqual("Fred", jed.sld_title) # replace style, verify changes self.cat.create_style("jed", open("test/ted.sld").read(), overwrite=True, workspace="topp") jed = self.cat.get_style("jed", workspace="topp") self.assert_(jed is not None) self.assertEqual("Ted", jed.sld_title) # delete style, verify non-existence self.cat.delete(jed, purge=True) self.assert_(self.cat.get_style("jed", workspace="topp") is None) # attempt creating new style self.cat.create_style("jed", open("test/fred.sld").read(), workspace="topp") jed = self.cat.get_style("jed", workspace="topp") self.assertEqual("Fred", jed.sld_title) # verify it can be found via URL and check the full name f = self.cat.get_style_by_url(jed.href) self.assert_(f is not None) self.assertEqual(f.fqn, jed.fqn) def testLayerWorkspaceStyles(self): # upload new style, verify existence self.cat.create_style("ned", open("test/fred.sld").read(), overwrite=True, workspace="topp") self.cat.create_style("zed", open("test/ted.sld").read(), overwrite=True, workspace="topp") ned = self.cat.get_style("ned", workspace="topp") zed = self.cat.get_style("zed", workspace="topp") self.assert_(ned is not None) self.assert_(zed is not None) lyr = self.cat.get_layer("states") lyr.default_style = ned lyr.styles = [zed] self.cat.save(lyr) self.assertEqual("topp:ned", lyr.default_style) self.assertEqual([zed], lyr.styles) lyr.refresh() self.assertEqual("topp:ned", lyr.default_style.fqn) self.assertEqual([zed.fqn], [s.fqn for s in lyr.styles]) def testWorkspaceCreate(self): ws = self.cat.get_workspace("acme") self.assertEqual(None, ws) self.cat.create_workspace("acme", "http://example.com/acme") ws = self.cat.get_workspace("acme") self.assertEqual("acme", ws.name) def testWorkspaceDelete(self): self.cat.create_workspace("foo", "http://example.com/foo") ws = self.cat.get_workspace("foo") self.cat.delete(ws) ws = self.cat.get_workspace("foo") self.assert_(ws is None) def testWorkspaceDefault(self): # save orig orig = self.cat.get_default_workspace() neu = self.cat.create_workspace("neu", "http://example.com/neu") try: # make sure setting it works self.cat.set_default_workspace("neu") ws = self.cat.get_default_workspace() self.assertEqual('neu', ws.name) finally: # cleanup and reset to the way things were self.cat.delete(neu) self.cat.set_default_workspace(orig.name) ws = self.cat.get_default_workspace() self.assertEqual(orig.name, ws.name) def testFeatureTypeDelete(self): pass def testCoverageDelete(self): pass def testDataStoreDelete(self): states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == True) states.enabled = False self.assert_(states.enabled == False) self.cat.save(states) states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == False) states.enabled = True self.cat.save(states) states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == True) def testLayerGroupSave(self): tas = self.cat.get_layergroup("tasmania") self.assertEqual(tas.layers, [ 'tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities' ], tas.layers) self.assertEqual(tas.styles, [None, None, None, None], tas.styles) tas.layers = tas.layers[:-1] tas.styles = tas.styles[:-1] self.cat.save(tas) # this verifies the local state self.assertEqual(tas.layers, [ 'tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads' ], tas.layers) self.assertEqual(tas.styles, [None, None, None], tas.styles) # force a refresh to check the remote state tas.refresh() self.assertEqual(tas.layers, [ 'tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads' ], tas.layers) self.assertEqual(tas.styles, [None, None, None], tas.styles) def testImageMosaic(self): """ Test case for Issue #110 """ # testing the mosaic creation name = 'cea_mosaic' data = open('test/data/mosaic/cea.zip', 'rb') self.cat.create_imagemosaic(name, data) # get the layer resource back self.cat._cache.clear() resource = self.cat.get_layer(name).resource self.assert_(resource is not None) # delete granule from mosaic coverage = name store = self.cat.get_store(name) granule_id = name + '.1' self.cat.mosaic_delete_granule(coverage, store, granule_id) def testTimeDimension(self): sf = self.cat.get_workspace("sf") files = shapefile_and_friends( os.path.join(gisdata.GOOD_DATA, "time", "boxes_with_end_date")) self.cat.create_featurestore("boxes_with_end_date", files, sf) get_resource = lambda: self.cat._cache.clear() or self.cat.get_layer( 'boxes_with_end_date').resource # configure time as LIST resource = get_resource() timeInfo = DimensionInfo("time", "true", "LIST", None, "ISO8601", None, attribute="date") resource.metadata = {'time': timeInfo} self.cat.save(resource) # and verify resource = get_resource() timeInfo = resource.metadata['time'] self.assertEqual("LIST", timeInfo.presentation) self.assertEqual(True, timeInfo.enabled) self.assertEqual("date", timeInfo.attribute) self.assertEqual("ISO8601", timeInfo.units) # disable time dimension timeInfo = resource.metadata['time'] timeInfo.enabled = False # since this is an xml property, it won't get written unless we modify it resource.metadata = {'time': timeInfo} self.cat.save(resource) # and verify resource = get_resource() timeInfo = resource.metadata['time'] self.assertEqual(False, timeInfo.enabled) # configure with interval, end_attribute and enable again timeInfo.enabled = True timeInfo.presentation = 'DISCRETE_INTERVAL' timeInfo.resolution = '3 days' timeInfo.end_attribute = 'enddate' resource.metadata = {'time': timeInfo} self.cat.save(resource) # and verify resource = get_resource() timeInfo = resource.metadata['time'] self.assertEqual(True, timeInfo.enabled) self.assertEqual('DISCRETE_INTERVAL', timeInfo.presentation) self.assertEqual('3 days', timeInfo.resolution_str()) self.assertEqual('enddate', timeInfo.end_attribute)
import requests from geoserver.catalog import Catalog # Set cat variable cat = Catalog('http://url/geoserver/rest/', username="******", password="******") # Create Workspace #ws = cat.create_workspace('ws_name','http://uri/ws_name') ws = cat.get_workspace('ws_name') # Create Store from PostGIS ds = cat.create_datastore('db_name', 'ws_name') ds.connection_parameters.update(host='host', port='5432', database='db_name', user='******', passwd='password', dbtype='postgis', schema='public') cat.save(ds) # Add Layers from Postgres ft = cat.publish_featuretype('table_name', ds, 'EPSG:3857', srs='EPSG:3857') cat.save(ft)
class CatalogTests(unittest.TestCase): def setUp(self): self.cat = Catalog(GSPARAMS['GSURL'], username=GSPARAMS['GSUSER'], password=GSPARAMS['GSPASSWORD']) def testAbout(self): about_html = self.cat.about() self.assertTrue( '<html xmlns="http://www.w3.org/1999/xhtml"' in about_html) def testGSVersion(self): version = self.cat.gsversion() pat = re.compile('\d\.\d(\.[\dx]|-SNAPSHOT)') self.assertTrue(pat.match('2.2.x')) self.assertTrue(pat.match('2.3.2')) self.assertTrue(pat.match('2.3-SNAPSHOT')) self.assertFalse(pat.match('2.3.y')) self.assertFalse(pat.match('233')) self.assertTrue(pat.match(version)) def testWorkspaces(self): self.assertEqual(7, len(self.cat.get_workspaces())) # marking out test since geoserver default workspace is not consistent # self.assertEqual("cite", self.cat.get_default_workspace().name) self.assertEqual("topp", self.cat.get_workspace("topp").name) def testStores(self): topp = self.cat.get_workspace("topp") sf = self.cat.get_workspace("sf") self.assertEqual(9, len(self.cat.get_stores())) self.assertEqual(2, len(self.cat.get_stores(topp))) self.assertEqual(2, len(self.cat.get_stores(sf))) self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile", topp).name) self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name) self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name) self.assertEqual("sfdem", self.cat.get_store("sfdem", sf).name) self.assertEqual("sfdem", self.cat.get_store("sfdem").name) def testResources(self): topp = self.cat.get_workspace("topp") sf = self.cat.get_workspace("sf") states = self.cat.get_store("states_shapefile", topp) sfdem = self.cat.get_store("sfdem", sf) self.assertEqual(19, len(self.cat.get_resources())) self.assertEqual(1, len(self.cat.get_resources(states))) self.assertEqual(5, len(self.cat.get_resources(workspace=topp))) self.assertEqual(1, len(self.cat.get_resources(sfdem))) self.assertEqual(6, len(self.cat.get_resources(workspace=sf))) self.assertEqual("states", self.cat.get_resource("states", states).name) self.assertEqual("states", self.cat.get_resource("states", workspace=topp).name) self.assertEqual("states", self.cat.get_resource("states").name) states = self.cat.get_resource("states") fields = [ states.title, states.abstract, states.native_bbox, states.latlon_bbox, states.projection, states.projection_policy ] self.assertFalse(None in fields, str(fields)) self.assertFalse(len(states.keywords) == 0) self.assertFalse(len(states.attributes) == 0) self.assertTrue(states.enabled) self.assertEqual("sfdem", self.cat.get_resource("sfdem", sfdem).name) self.assertEqual("sfdem", self.cat.get_resource("sfdem", workspace=sf).name) self.assertEqual("sfdem", self.cat.get_resource("sfdem").name) def testResourcesUpdate(self): res_dest = self.cat.get_resources() count = 0 for rd in res_dest: # only wms layers if rd.resource_type != "wmsLayer": continue # looking for same name ro = self.cat.get_resource(rd.name) if ro is not None: rd.title = ro.title rd.abstract = ro.abstract rd.keywords = ro.keywords rd.projection = ro.projection rd.native_bbox = ro.native_bbox rd.latlon_bbox = ro.latlon_bbox rd.projection_policy = ro.projection_policy rd.enabled = ro.enabled rd.advertised = ro.advertised rd.metadata_links = ro.metadata_links or None self.cat.save(rd) self.cat.reload() # print "Updated layer: " + rd.name count += 1 # print "Total updated layers: " + str(count) def testLayers(self): expected = set([ "Arc_Sample", "Pk50095", "Img_Sample", "mosaic", "sfdem", "bugsites", "restricted", "streams", "archsites", "roads", "tasmania_roads", "tasmania_water_bodies", "tasmania_state_boundaries", "tasmania_cities", "states", "poly_landmarks", "tiger_roads", "poi", "giant_polygon" ]) actual = set(l.name for l in self.cat.get_layers()) missing = expected - actual extras = actual - expected message = "Actual layer list did not match expected! (Extras: %s) (Missing: %s)" % ( extras, missing) self.assert_(len(expected ^ actual) == 0, message) states = self.cat.get_layer("states") self.assert_("states", states.name) self.assert_(isinstance(states.resource, ResourceInfo)) self.assertEqual(set(s.name for s in states.styles), set(['pophatch', 'polygon'])) self.assertEqual(states.default_style.name, "population") def testLayerGroups(self): expected = set(["tasmania", "tiger-ny", "spearfish"]) actual = set(l.name for l in self.cat.get_layergroups()) missing = expected - actual extras = actual - expected message = "Actual layergroup list did not match expected! (Extras: %s) (Missing: %s)" % ( extras, missing) self.assert_(len(expected ^ actual) == 0, message) tas = self.cat.get_layergroup("tasmania") self.assert_("tasmania", tas.name) self.assert_(isinstance(tas, LayerGroup)) self.assertEqual(tas.layers, [ 'tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities' ], tas.layers) self.assertEqual(tas.styles, [None, None, None, None], tas.styles) # Try to create a new Layer Group into the "topp" workspace self.assert_(self.cat.get_workspace("topp") is not None) tas2 = self.cat.create_layergroup("tasmania_reloaded", tas.layers, workspace="topp") self.cat.save(tas2) self.assert_(self.cat.get_layergroup("tasmania_reloaded") is None) self.assert_( self.cat.get_layergroup("tasmania_reloaded", "topp") is not None) tas2 = self.cat.get_layergroup("tasmania_reloaded", "topp") self.assert_("tasmania_reloaded", tas2.name) self.assert_(isinstance(tas2, LayerGroup)) self.assertEqual(tas2.workspace, "topp", tas2.workspace) self.assertEqual(tas2.layers, [ 'tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities' ], tas2.layers) self.assertEqual(tas2.styles, [None, None, None, None], tas2.styles) def testStyles(self): self.assertEqual("population", self.cat.get_style("population").name) self.assertEqual("popshade.sld", self.cat.get_style("population").filename) self.assertEqual("population", self.cat.get_style("population").sld_name) self.assert_(self.cat.get_style('non-existing-style') is None) def testEscaping(self): # GSConfig is inconsistent about using exceptions vs. returning None # when a resource isn't found. # But the basic idea is that none of them should throw HTTP errors from # misconstructed URLS self.cat.get_style("best style ever") self.cat.get_workspace("best workspace ever") try: self.cat.get_store(workspace="best workspace ever", name="best store ever") self.fail('expected exception') except FailedRequestError, fre: self.assertEqual('No store found named: best store ever', fre.message) try: self.cat.get_resource(workspace="best workspace ever", store="best store ever", name="best resource ever") except FailedRequestError, fre: self.assertEqual('No store found named: best store ever', fre.message)
class ModifyingTests(unittest.TestCase): def setUp(self): self.cat = Catalog("http://localhost:8080/geoserver/rest") def testFeatureTypeSave(self): # test saving round trip rs = self.cat.get_resource("bugsites") old_abstract = rs.abstract new_abstract = "Not the original abstract" enabled = rs.enabled # Change abstract on server rs.abstract = new_abstract self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(new_abstract, rs.abstract) self.assertEqual(enabled, rs.enabled) # Change keywords on server rs.keywords = ["bugsites", "gsconfig"] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(["bugsites", "gsconfig"], rs.keywords) self.assertEqual(enabled, rs.enabled) # Change metadata links on server rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual( [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")], rs.metadata_links) self.assertEqual(enabled, rs.enabled) # Restore abstract rs.abstract = old_abstract self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(old_abstract, rs.abstract) def testDataStoreCreate(self): ds = self.cat.create_datastore("vector_gsconfig") ds.connection_parameters.update( host="localhost", port="5432", database="db", user="******", passwd="password", dbtype="postgis") self.cat.save(ds) def testDataStoreModify(self): ds = self.cat.get_store("sf") self.assertFalse("foo" in ds.connection_parameters) ds.connection_parameters = ds.connection_parameters ds.connection_parameters["foo"] = "bar" orig_ws = ds.workspace.name self.cat.save(ds) ds = self.cat.get_store("sf") self.assertTrue("foo" in ds.connection_parameters) self.assertEqual("bar", ds.connection_parameters["foo"]) self.assertEqual(orig_ws, ds.workspace.name) def testDataStoreCreateAndThenAlsoImportData(self): ds = self.cat.create_datastore("gsconfig_import_test") ds.connection_parameters.update( host="localhost", port="5432", database="db", user="******", passwd="password", dbtype="postgis") self.cat.save(ds) ds = self.cat.get_store("gsconfig_import_test") self.cat.add_data_to_store(ds, "import", { 'shp': 'test/data/states.shp', 'shx': 'test/data/states.shx', 'dbf': 'test/data/states.dbf', 'prj': 'test/data/states.prj' }) def testCoverageStoreCreate(self): ds = self.cat.create_coveragestore2("coverage_gsconfig") ds.data_url = "file:data/mytiff.tiff" self.cat.save(ds) def testCoverageStoreModify(self): cs = self.cat.get_store("sfdem") self.assertEqual("GeoTIFF", cs.type) cs.type = "WorldImage" self.cat.save(cs) cs = self.cat.get_store("sfdem") self.assertEqual("WorldImage", cs.type) # not sure about order of test runs here, but it might cause problems # for other tests if this layer is misconfigured cs.type = "GeoTIFF" self.cat.save(cs) def testCoverageSave(self): # test saving round trip rs = self.cat.get_resource("Arc_Sample") old_abstract = rs.abstract new_abstract = "Not the original abstract" # # Change abstract on server rs.abstract = new_abstract self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual(new_abstract, rs.abstract) # Restore abstract rs.abstract = old_abstract self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual(old_abstract, rs.abstract) # Change metadata links on server rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual( [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")], rs.metadata_links) self.assertEqual(enabled, rs.enabled) srs_before = set(['EPSG:4326']) srs_after = set(['EPSG:4326', 'EPSG:3785']) formats = set(['ARCGRID', 'ARCGRID-GZIP', 'GEOTIFF', 'PNG', 'GIF', 'TIFF']) formats_after = set(["PNG", "GIF", "TIFF"]) # set and save request_srs_list self.assertEquals(set(rs.request_srs_list), srs_before, str(rs.request_srs_list)) rs.request_srs_list = rs.request_srs_list + ['EPSG:3785'] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.request_srs_list), srs_after, str(rs.request_srs_list)) # set and save response_srs_list self.assertEquals(set(rs.response_srs_list), srs_before, str(rs.response_srs_list)) rs.response_srs_list = rs.response_srs_list + ['EPSG:3785'] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.response_srs_list), srs_after, str(rs.response_srs_list)) # set and save supported_formats self.assertEquals(set(rs.supported_formats), formats, str(rs.supported_formats)) rs.supported_formats = ["PNG", "GIF", "TIFF"] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.supported_formats), formats_after, str(rs.supported_formats)) def testFeatureTypeCreate(self): shapefile_plus_sidecars = shapefile_and_friends("test/data/states") expected = { 'shp': 'test/data/states.shp', 'shx': 'test/data/states.shx', 'dbf': 'test/data/states.dbf', 'prj': 'test/data/states.prj' } self.assertEqual(len(expected), len(shapefile_plus_sidecars)) for k, v in expected.iteritems(): self.assertEqual(v, shapefile_plus_sidecars[k]) sf = self.cat.get_workspace("sf") self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf) self.assert_(self.cat.get_resource("states_test", workspace=sf) is not None) self.assertRaises( ConflictingDataError, lambda: self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf) ) self.assertRaises( UploadError, lambda: self.cat.create_coveragestore("states_raster_test", shapefile_plus_sidecars, sf) ) bogus_shp = { 'shp': 'test/data/Pk50095.tif', 'shx': 'test/data/Pk50095.tif', 'dbf': 'test/data/Pk50095.tfw', 'prj': 'test/data/Pk50095.prj' } self.assertRaises( UploadError, lambda: self.cat.create_featurestore("bogus_shp", bogus_shp, sf) ) lyr = self.cat.get_layer("states_test") self.cat.delete(lyr) self.assert_(self.cat.get_layer("states_test") is None) def testCoverageCreate(self): tiffdata = { 'tiff': 'test/data/Pk50095.tif', 'tfw': 'test/data/Pk50095.tfw', 'prj': 'test/data/Pk50095.prj' } sf = self.cat.get_workspace("sf") # TODO: Uploading WorldImage file no longer works??? # ft = self.cat.create_coveragestore("Pk50095", tiffdata, sf) # self.assert_(self.cat.get_resource("Pk50095", workspace=sf) is not None) # self.assertRaises( # ConflictingDataError, # lambda: self.cat.create_coveragestore("Pk50095", tiffdata, sf) # ) self.assertRaises( UploadError, lambda: self.cat.create_featurestore("Pk50095_vector", tiffdata, sf) ) bogus_tiff = { 'tiff': 'test/data/states.shp', 'tfw': 'test/data/states.shx', 'prj': 'test/data/states.prj' } self.assertRaises( UploadError, lambda: self.cat.create_coveragestore("states_raster", bogus_tiff) ) def testLayerSave(self): # test saving round trip lyr = self.cat.get_layer("states") old_attribution = lyr.attribution new_attribution = "Not the original attribution" # change attribution on server lyr.attribution = new_attribution self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(new_attribution, lyr.attribution) # Restore attribution lyr.attribution = old_attribution self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(old_attribution, lyr.attribution) self.assertEqual(lyr.default_style.name, "population") old_default_style = lyr.default_style lyr.default_style = (s for s in lyr.styles if s.name == "pophatch").next() lyr.styles = [old_default_style] self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(lyr.default_style.name, "pophatch") self.assertEqual([s.name for s in lyr.styles], ["population"]) def testStyles(self): # upload new style, verify existence self.cat.create_style("fred", open("test/fred.sld").read()) fred = self.cat.get_style("fred") self.assert_(fred is not None) self.assertEqual("Fred", fred.sld_title) # replace style, verify changes self.cat.create_style("fred", open("test/ted.sld").read(), overwrite=True) fred = self.cat.get_style("fred") self.assert_(fred is not None) self.assertEqual("Ted", fred.sld_title) # delete style, verify non-existence self.cat.delete(fred, purge=True) self.assert_(self.cat.get_style("fred") is None) # attempt creating new style self.cat.create_style("fred", open("test/fred.sld").read()) fred = self.cat.get_style("fred") self.assertEqual("Fred", fred.sld_title) def testWorkspaceCreate(self): ws = self.cat.get_workspace("acme") self.assertEqual(None, ws) self.cat.create_workspace("acme", "http://example.com/acme") ws = self.cat.get_workspace("acme") self.assertEqual("acme", ws.name) def testWorkspaceDelete(self): self.cat.create_workspace("foo", "http://example.com/foo") ws = self.cat.get_workspace("foo") self.cat.delete(ws) ws = self.cat.get_workspace("foo") self.assert_(ws is None) def testFeatureTypeDelete(self): pass def testCoverageDelete(self): pass def testDataStoreDelete(self): states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == True) states.enabled = False self.assert_(states.enabled == False) self.cat.save(states) states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == False) states.enabled = True self.cat.save(states) states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == True) def testLayerGroupSave(self): tas = self.cat.get_layergroup("tasmania") self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers) self.assertEqual(tas.styles, [None, None, None, None], tas.styles) tas.layers = tas.layers[:-1] tas.styles = tas.styles[:-1] self.cat.save(tas) self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads'], tas.layers) self.assertEqual(tas.styles, [None, None, None], tas.styles)
class CatalogTests(unittest.TestCase): def setUp(self): self.cat = Catalog(GSPARAMS['GSURL'], username=GSPARAMS['GSUSER'], password=GSPARAMS['GSPASSWORD']) def testAbout(self): about_html = self.cat.about() self.assertTrue('<html xmlns="http://www.w3.org/1999/xhtml"' in about_html) def testGSVersion(self): version = self.cat.gsversion() pat = re.compile('\d\.\d(\.[\dx]|-SNAPSHOT)') self.assertTrue(pat.match('2.2.x')) self.assertTrue(pat.match('2.3.2')) self.assertTrue(pat.match('2.3-SNAPSHOT')) self.assertFalse(pat.match('2.3.y')) self.assertFalse(pat.match('233')) self.assertTrue(pat.match(version)) def testWorkspaces(self): self.assertEqual(7, len(self.cat.get_workspaces())) # marking out test since geoserver default workspace is not consistent # self.assertEqual("cite", self.cat.get_default_workspace().name) self.assertEqual("topp", self.cat.get_workspace("topp").name) def testStores(self): topp = self.cat.get_workspace("topp") sf = self.cat.get_workspace("sf") self.assertEqual(9, len(self.cat.get_stores())) self.assertEqual(2, len(self.cat.get_stores(topp))) self.assertEqual(2, len(self.cat.get_stores(sf))) self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile", topp).name) self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name) self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name) self.assertEqual("sfdem", self.cat.get_store("sfdem", sf).name) self.assertEqual("sfdem", self.cat.get_store("sfdem").name) def testResources(self): topp = self.cat.get_workspace("topp") sf = self.cat.get_workspace("sf") states = self.cat.get_store("states_shapefile", topp) sfdem = self.cat.get_store("sfdem", sf) self.assertEqual(19, len(self.cat.get_resources())) self.assertEqual(1, len(self.cat.get_resources(states))) self.assertEqual(5, len(self.cat.get_resources(workspace=topp))) self.assertEqual(1, len(self.cat.get_resources(sfdem))) self.assertEqual(6, len(self.cat.get_resources(workspace=sf))) self.assertEqual("states", self.cat.get_resource("states", states).name) self.assertEqual("states", self.cat.get_resource("states", workspace=topp).name) self.assertEqual("states", self.cat.get_resource("states").name) states = self.cat.get_resource("states") fields = [ states.title, states.abstract, states.native_bbox, states.latlon_bbox, states.projection, states.projection_policy ] self.assertFalse(None in fields, str(fields)) self.assertFalse(len(states.keywords) == 0) self.assertFalse(len(states.attributes) == 0) self.assertTrue(states.enabled) self.assertEqual("sfdem", self.cat.get_resource("sfdem", sfdem).name) self.assertEqual("sfdem", self.cat.get_resource("sfdem", workspace=sf).name) self.assertEqual("sfdem", self.cat.get_resource("sfdem").name) def testResourcesUpdate(self): res_dest = self.cat.get_resources() count = 0 for rd in res_dest: # only wms layers if rd.resource_type != "wmsLayer": continue # looking for same name ro = self.cat.get_resource(rd.name) if ro is not None: rd.title = ro.title rd.abstract = ro.abstract rd.keywords = ro.keywords rd.projection = ro.projection rd.native_bbox = ro.native_bbox rd.latlon_bbox = ro.latlon_bbox rd.projection_policy = ro.projection_policy rd.enabled = ro.enabled rd.advertised = ro.advertised rd.metadata_links = ro.metadata_links or None self.cat.save(rd) self.cat.reload() # print "Updated layer: " + rd.name count += 1 # print "Total updated layers: " + str(count) def testLayers(self): expected = set(["Arc_Sample", "Pk50095", "Img_Sample", "mosaic", "sfdem", "bugsites", "restricted", "streams", "archsites", "roads", "tasmania_roads", "tasmania_water_bodies", "tasmania_state_boundaries", "tasmania_cities", "states", "poly_landmarks", "tiger_roads", "poi", "giant_polygon" ]) actual = set(l.name for l in self.cat.get_layers()) missing = expected - actual extras = actual - expected message = "Actual layer list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing) self.assert_(len(expected ^ actual) == 0, message) states = self.cat.get_layer("states") self.assert_("states", states.name) self.assert_(isinstance(states.resource, ResourceInfo)) self.assertEqual(set(s.name for s in states.styles), set(['pophatch', 'polygon'])) self.assertEqual(states.default_style.name, "population") def testLayerGroups(self): expected = set(["tasmania", "tiger-ny", "spearfish"]) actual = set(l.name for l in self.cat.get_layergroups()) missing = expected - actual extras = actual - expected message = "Actual layergroup list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing) self.assert_(len(expected ^ actual) == 0, message) tas = self.cat.get_layergroup("tasmania") self.assert_("tasmania", tas.name) self.assert_(isinstance(tas, LayerGroup)) self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers) self.assertEqual(tas.styles, [None, None, None, None], tas.styles) # Try to create a new Layer Group into the "topp" workspace self.assert_(self.cat.get_workspace("topp") is not None) tas2 = self.cat.create_layergroup("tasmania_reloaded", tas.layers, workspace = "topp") self.cat.save(tas2) self.assert_(self.cat.get_layergroup("tasmania_reloaded") is None) self.assert_(self.cat.get_layergroup("tasmania_reloaded", "topp") is not None) tas2 = self.cat.get_layergroup("tasmania_reloaded", "topp") self.assert_("tasmania_reloaded", tas2.name) self.assert_(isinstance(tas2, LayerGroup)) self.assertEqual(tas2.workspace, "topp", tas2.workspace) self.assertEqual(tas2.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas2.layers) self.assertEqual(tas2.styles, [None, None, None, None], tas2.styles) def testStyles(self): self.assertEqual("population", self.cat.get_style("population").name) self.assertEqual("popshade.sld", self.cat.get_style("population").filename) self.assertEqual("population", self.cat.get_style("population").sld_name) self.assert_(self.cat.get_style('non-existing-style') is None) def testEscaping(self): # GSConfig is inconsistent about using exceptions vs. returning None # when a resource isn't found. # But the basic idea is that none of them should throw HTTP errors from # misconstructed URLS self.cat.get_style("best style ever") self.cat.get_workspace("best workspace ever") try: self.cat.get_store(workspace="best workspace ever", name="best store ever") self.fail('expected exception') except FailedRequestError, fre: self.assertEqual('No store found named: best store ever', fre.message) try: self.cat.get_resource(workspace="best workspace ever", store="best store ever", name="best resource ever") except FailedRequestError, fre: self.assertEqual('No store found named: best store ever', fre.message)
class CatalogTests(unittest.TestCase): def setUp(self): self.cat = Catalog("http://localhost:8080/geoserver/rest") def testWorkspaces(self): self.assertEqual(7, len(self.cat.get_workspaces())) # marking out test since geoserver default workspace is not consistent # self.assertEqual("cite", self.cat.get_default_workspace().name) self.assertEqual("topp", self.cat.get_workspace("topp").name) def testStores(self): topp = self.cat.get_workspace("topp") sf = self.cat.get_workspace("sf") self.assertEqual(9, len(self.cat.get_stores())) self.assertEqual(2, len(self.cat.get_stores(topp))) self.assertEqual(2, len(self.cat.get_stores(sf))) self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile", topp).name) self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name) self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name) self.assertEqual("sfdem", self.cat.get_store("sfdem", sf).name) self.assertEqual("sfdem", self.cat.get_store("sfdem").name) def testResources(self): topp = self.cat.get_workspace("topp") sf = self.cat.get_workspace("sf") states = self.cat.get_store("states_shapefile", topp) sfdem = self.cat.get_store("sfdem", sf) self.assertEqual(19, len(self.cat.get_resources())) self.assertEqual(1, len(self.cat.get_resources(states))) self.assertEqual(5, len(self.cat.get_resources(workspace=topp))) self.assertEqual(1, len(self.cat.get_resources(sfdem))) self.assertEqual(6, len(self.cat.get_resources(workspace=sf))) self.assertEqual("states", self.cat.get_resource("states", states).name) self.assertEqual("states", self.cat.get_resource("states", workspace=topp).name) self.assertEqual("states", self.cat.get_resource("states").name) states = self.cat.get_resource("states") fields = [ states.title, states.abstract, states.native_bbox, states.latlon_bbox, states.projection, states.projection_policy ] self.assertFalse(None in fields, str(fields)) self.assertFalse(len(states.keywords) == 0) self.assertFalse(len(states.attributes) == 0) self.assertTrue(states.enabled) self.assertEqual("sfdem", self.cat.get_resource("sfdem", sfdem).name) self.assertEqual("sfdem", self.cat.get_resource("sfdem", workspace=sf).name) self.assertEqual("sfdem", self.cat.get_resource("sfdem").name) def testLayers(self): expected = set(["Arc_Sample", "Pk50095", "Img_Sample", "mosaic", "sfdem", "bugsites", "restricted", "streams", "archsites", "roads", "tasmania_roads", "tasmania_water_bodies", "tasmania_state_boundaries", "tasmania_cities", "states", "poly_landmarks", "tiger_roads", "poi", "giant_polygon" ]) actual = set(l.name for l in self.cat.get_layers()) missing = expected - actual extras = actual - expected message = "Actual layer list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing) self.assert_(len(expected ^ actual) == 0, message) states = self.cat.get_layer("states") self.assert_("states", states.name) self.assert_(isinstance(states.resource, ResourceInfo)) self.assertEqual(set(s.name for s in states.styles), set(['pophatch', 'polygon'])) self.assertEqual(states.default_style.name, "population") def testLayerGroups(self): expected = set(["tasmania", "tiger-ny", "spearfish"]) actual = set(l.name for l in self.cat.get_layergroups()) missing = expected - actual extras = actual - expected message = "Actual layergroup list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing) self.assert_(len(expected ^ actual) == 0, message) tas = self.cat.get_layergroup("tasmania") self.assert_("tasmania", tas.name) self.assert_(isinstance(tas, LayerGroup)) self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers) self.assertEqual(tas.styles, [None, None, None, None], tas.styles) def testStyles(self): self.assertEqual(20, len(self.cat.get_styles())) self.assertEqual("population", self.cat.get_style("population").name)
def export_geoserver(request): project = request.POST.get('project', False) workspace_name = request.POST.get('workspace', 'geoglows_hydroviewer_creator') store_name = request.POST.get('store_name', 'shapefilestore') store_name = str(store_name).replace(' ', '_') store_name = str.lower(store_name) if not project: return JsonResponse({'error': 'unable to find the project'}) proj_dir = get_project_directory(project) # tailor the geoserver url url = request.POST.get('gs_url') if not url[-1] == '/': url += '/' # add keys to the export_configs.json with open(os.path.join(proj_dir, 'export_configs.json'), 'r') as configfile: geoserver_configs = json.loads(configfile.read()) geoserver_configs['url'] = url.replace('/rest/', f'/{workspace_name}/wms') geoserver_configs['workspace'] = workspace_name geoserver_configs['drainage_layer_name'] = str.lower( project) + '_drainagelines' geoserver_configs['catchment_layer_name'] = str.lower( project) + '_catchments' if geoserver_configs['exported_drainage'] and geoserver_configs[ 'exported_catchment']: geoserver_configs['exported_drainage'] = False geoserver_configs['exported_catchment'] = False try: cat = Catalog(url, username=request.POST.get('gs_username', 'admin'), password=request.POST.get('gs_password', 'geoserver')) # identify the geoserver stores workspace = cat.get_workspace(workspace_name) except Exception as e: print(e) return JsonResponse({'status': 'failed'}) if not geoserver_configs['exported_drainage']: try: # create geoserver store and upload the drainagelines zip_path = os.path.join(proj_dir, 'drainageline_shapefile.zip') cat.create_featurestore(store_name, workspace=workspace, data=zip_path, overwrite=True) geoserver_configs['exported_drainage'] = True with open(os.path.join(proj_dir, 'export_configs.json'), 'w') as configfile: configfile.write(json.dumps(geoserver_configs)) except Exception as e: print('failed to upload drainagelines') print(e) elif not geoserver_configs['exported_catchment']: try: # create geoserver store and upload the catchments zip_path = os.path.join(proj_dir, 'catchment_shapefile.zip') cat.add_data_to_store(store_name, store_name, data=zip_path, workspace=workspace, overwrite=False) geoserver_configs['exported_catchment'] = True with open(os.path.join(proj_dir, 'export_configs.json'), 'w') as configfile: configfile.write(json.dumps(geoserver_configs)) except Exception as e: print('failed to upload catchments') print(e) return JsonResponse({'status': 'success'})
class ModifyingTests(unittest.TestCase): def setUp(self): self.cat = Catalog("http://localhost:8080/geoserver/rest") def testFeatureTypeSave(self): # test saving round trip rs = self.cat.get_resource("bugsites") old_abstract = rs.abstract new_abstract = "Not the original abstract" enabled = rs.enabled # Change abstract on server rs.abstract = new_abstract self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(new_abstract, rs.abstract) self.assertEqual(enabled, rs.enabled) # Change keywords on server rs.keywords = ["bugsites", "gsconfig"] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(["bugsites", "gsconfig"], rs.keywords) self.assertEqual(enabled, rs.enabled) # Change metadata links on server rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual( [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")], rs.metadata_links) self.assertEqual(enabled, rs.enabled) # Restore abstract rs.abstract = old_abstract self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(old_abstract, rs.abstract) def testDataStoreCreate(self): ds = self.cat.create_datastore("vector_gsconfig") ds.connection_parameters.update(**DBPARAMS) self.cat.save(ds) def testPublishFeatureType(self): # Use the other test and store creation to load vector data into a database # @todo maybe load directly to database? try: self.testDataStoreCreateAndThenAlsoImportData() except FailedRequestError: pass try: lyr = self.cat.get_layer('import') # Delete the existing layer and resource to allow republishing. self.cat.delete(lyr) self.cat.delete(lyr.resource) ds = self.cat.get_store("gsconfig_import_test") # make sure it's gone self.assert_(self.cat.get_layer('import') is None) self.cat.publish_featuretype("import", ds, native_crs="EPSG:4326") # and now it's not self.assert_(self.cat.get_layer('import') is not None) finally: # tear stuff down to allow the other test to pass if we run first ds = self.cat.get_store("gsconfig_import_test") lyr = self.cat.get_layer('import') # Delete the existing layer and resource to allow republishing. self.cat.delete(lyr) self.cat.delete(lyr.resource) self.cat.delete(ds) def testDataStoreModify(self): ds = self.cat.get_store("sf") self.assertFalse("foo" in ds.connection_parameters) ds.connection_parameters = ds.connection_parameters ds.connection_parameters["foo"] = "bar" orig_ws = ds.workspace.name self.cat.save(ds) ds = self.cat.get_store("sf") self.assertTrue("foo" in ds.connection_parameters) self.assertEqual("bar", ds.connection_parameters["foo"]) self.assertEqual(orig_ws, ds.workspace.name) @drop_table('import') def testDataStoreCreateAndThenAlsoImportData(self): ds = self.cat.create_datastore("gsconfig_import_test") ds.connection_parameters.update(**DBPARAMS) self.cat.save(ds) ds = self.cat.get_store("gsconfig_import_test") self.cat.add_data_to_store(ds, "import", { 'shp': 'test/data/states.shp', 'shx': 'test/data/states.shx', 'dbf': 'test/data/states.dbf', 'prj': 'test/data/states.prj' }) def testCoverageStoreCreate(self): ds = self.cat.create_coveragestore2("coverage_gsconfig") ds.data_url = "file:data/mytiff.tiff" self.cat.save(ds) def testCoverageStoreModify(self): cs = self.cat.get_store("sfdem") self.assertEqual("GeoTIFF", cs.type) cs.type = "WorldImage" self.cat.save(cs) cs = self.cat.get_store("sfdem") self.assertEqual("WorldImage", cs.type) # not sure about order of test runs here, but it might cause problems # for other tests if this layer is misconfigured cs.type = "GeoTIFF" self.cat.save(cs) def testCoverageSave(self): # test saving round trip rs = self.cat.get_resource("Arc_Sample") old_abstract = rs.abstract new_abstract = "Not the original abstract" # # Change abstract on server rs.abstract = new_abstract self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual(new_abstract, rs.abstract) # Restore abstract rs.abstract = old_abstract self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual(old_abstract, rs.abstract) # Change metadata links on server rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual( [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")], rs.metadata_links) self.assertEqual(enabled, rs.enabled) srs_before = set(['EPSG:4326']) srs_after = set(['EPSG:4326', 'EPSG:3785']) formats = set(['ARCGRID', 'ARCGRID-GZIP', 'GEOTIFF', 'PNG', 'GIF', 'TIFF']) formats_after = set(["PNG", "GIF", "TIFF"]) # set and save request_srs_list self.assertEquals(set(rs.request_srs_list), srs_before, str(rs.request_srs_list)) rs.request_srs_list = rs.request_srs_list + ['EPSG:3785'] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.request_srs_list), srs_after, str(rs.request_srs_list)) # set and save response_srs_list self.assertEquals(set(rs.response_srs_list), srs_before, str(rs.response_srs_list)) rs.response_srs_list = rs.response_srs_list + ['EPSG:3785'] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.response_srs_list), srs_after, str(rs.response_srs_list)) # set and save supported_formats self.assertEquals(set(rs.supported_formats), formats, str(rs.supported_formats)) rs.supported_formats = ["PNG", "GIF", "TIFF"] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.supported_formats), formats_after, str(rs.supported_formats)) def testWmsStoreCreate(self): ws = self.cat.create_wmsstore("wmsstore_gsconfig") ws.capabilitiesURL = "http://suite.opengeo.org/geoserver/ows?service=wms&version=1.1.1&request=GetCapabilities" ws.type = "WMS" self.cat.save(ws) def testWmsLayer(self): self.cat.create_workspace("wmstest", "http://example.com/wmstest") wmstest = self.cat.get_workspace("wmstest") wmsstore = self.cat.create_wmsstore("wmsstore", wmstest) wmsstore.capabilitiesURL = "http://suite.opengeo.org/geoserver/ows?service=wms&version=1.1.1&request=GetCapabilities" wmsstore.type = "WMS" self.cat.save(wmsstore) wmsstore = self.cat.get_store("wmsstore") self.assertEqual(1, len(self.cat.get_stores(wmstest))) available_layers = wmsstore.get_resources(available=True) for layer in available_layers: new_layer = self.cat.create_wmslayer(wmstest, wmsstore, layer) added_layers = wmsstore.get_resources() self.assertEqual(len(available_layers), len(added_layers)) def testFeatureTypeCreate(self): shapefile_plus_sidecars = shapefile_and_friends("test/data/states") expected = { 'shp': 'test/data/states.shp', 'shx': 'test/data/states.shx', 'dbf': 'test/data/states.dbf', 'prj': 'test/data/states.prj' } self.assertEqual(len(expected), len(shapefile_plus_sidecars)) for k, v in expected.iteritems(): self.assertEqual(v, shapefile_plus_sidecars[k]) sf = self.cat.get_workspace("sf") self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf) self.assert_(self.cat.get_resource("states_test", workspace=sf) is not None) self.assertRaises( ConflictingDataError, lambda: self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf) ) self.assertRaises( UploadError, lambda: self.cat.create_coveragestore("states_raster_test", shapefile_plus_sidecars, sf) ) bogus_shp = { 'shp': 'test/data/Pk50095.tif', 'shx': 'test/data/Pk50095.tif', 'dbf': 'test/data/Pk50095.tfw', 'prj': 'test/data/Pk50095.prj' } self.assertRaises( UploadError, lambda: self.cat.create_featurestore("bogus_shp", bogus_shp, sf) ) lyr = self.cat.get_layer("states_test") self.cat.delete(lyr) self.assert_(self.cat.get_layer("states_test") is None) def testCoverageCreate(self): tiffdata = { 'tiff': 'test/data/Pk50095.tif', 'tfw': 'test/data/Pk50095.tfw', 'prj': 'test/data/Pk50095.prj' } sf = self.cat.get_workspace("sf") # TODO: Uploading WorldImage file no longer works??? # ft = self.cat.create_coveragestore("Pk50095", tiffdata, sf) # self.assert_(self.cat.get_resource("Pk50095", workspace=sf) is not None) # self.assertRaises( # ConflictingDataError, # lambda: self.cat.create_coveragestore("Pk50095", tiffdata, sf) # ) self.assertRaises( UploadError, lambda: self.cat.create_featurestore("Pk50095_vector", tiffdata, sf) ) bogus_tiff = { 'tiff': 'test/data/states.shp', 'tfw': 'test/data/states.shx', 'prj': 'test/data/states.prj' } self.assertRaises( UploadError, lambda: self.cat.create_coveragestore("states_raster", bogus_tiff) ) def testLayerSave(self): # test saving round trip lyr = self.cat.get_layer("states") old_attribution = lyr.attribution new_attribution = "Not the original attribution" # change attribution on server lyr.attribution = new_attribution self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(new_attribution, lyr.attribution) # Restore attribution lyr.attribution = old_attribution self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(old_attribution, lyr.attribution) self.assertEqual(lyr.default_style.name, "population") old_default_style = lyr.default_style lyr.default_style = (s for s in lyr.styles if s.name == "pophatch").next() lyr.styles = [old_default_style] self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(lyr.default_style.name, "pophatch") self.assertEqual([s.name for s in lyr.styles], ["population"]) def testStyles(self): # upload new style, verify existence self.cat.create_style("fred", open("test/fred.sld").read()) fred = self.cat.get_style("fred") self.assert_(fred is not None) self.assertEqual("Fred", fred.sld_title) # replace style, verify changes self.cat.create_style("fred", open("test/ted.sld").read(), overwrite=True) fred = self.cat.get_style("fred") self.assert_(fred is not None) self.assertEqual("Ted", fred.sld_title) # delete style, verify non-existence self.cat.delete(fred, purge=True) self.assert_(self.cat.get_style("fred") is None) # attempt creating new style self.cat.create_style("fred", open("test/fred.sld").read()) fred = self.cat.get_style("fred") self.assertEqual("Fred", fred.sld_title) # verify it can be found via URL and check the name f = self.cat.get_style_by_url(fred.href) self.assert_(f is not None) self.assertEqual(f.name, fred.name) def testWorkspaceStyles(self): # upload new style, verify existence self.cat.create_style("jed", open("test/fred.sld").read(), workspace="topp") jed = self.cat.get_style("jed", workspace="blarny") self.assert_(jed is None) jed = self.cat.get_style("jed", workspace="topp") self.assert_(jed is not None) self.assertEqual("Fred", jed.sld_title) jed = self.cat.get_style("topp:jed") self.assert_(jed is not None) self.assertEqual("Fred", jed.sld_title) # replace style, verify changes self.cat.create_style("jed", open("test/ted.sld").read(), overwrite=True, workspace="topp") jed = self.cat.get_style("jed", workspace="topp") self.assert_(jed is not None) self.assertEqual("Ted", jed.sld_title) # delete style, verify non-existence self.cat.delete(jed, purge=True) self.assert_(self.cat.get_style("jed", workspace="topp") is None) # attempt creating new style self.cat.create_style("jed", open("test/fred.sld").read(), workspace="topp") jed = self.cat.get_style("jed", workspace="topp") self.assertEqual("Fred", jed.sld_title) # verify it can be found via URL and check the full name f = self.cat.get_style_by_url(jed.href) self.assert_(f is not None) self.assertEqual(f.fqn, jed.fqn) def testLayerWorkspaceStyles(self): # upload new style, verify existence self.cat.create_style("ned", open("test/fred.sld").read(), overwrite=True, workspace="topp") self.cat.create_style("zed", open("test/ted.sld").read(), overwrite=True, workspace="topp") ned = self.cat.get_style("ned", workspace="topp") zed = self.cat.get_style("zed", workspace="topp") self.assert_(ned is not None) self.assert_(zed is not None) lyr = self.cat.get_layer("states") lyr.default_style = ned lyr.styles = [zed] self.cat.save(lyr) self.assertEqual("topp:ned", lyr.default_style) self.assertEqual([zed], lyr.styles) lyr.refresh() self.assertEqual("topp:ned", lyr.default_style.fqn) self.assertEqual([zed.fqn], [s.fqn for s in lyr.styles]) def testWorkspaceCreate(self): ws = self.cat.get_workspace("acme") self.assertEqual(None, ws) self.cat.create_workspace("acme", "http://example.com/acme") ws = self.cat.get_workspace("acme") self.assertEqual("acme", ws.name) def testWorkspaceDelete(self): self.cat.create_workspace("foo", "http://example.com/foo") ws = self.cat.get_workspace("foo") self.cat.delete(ws) ws = self.cat.get_workspace("foo") self.assert_(ws is None) def testWorkspaceDefault(self): # save orig orig = self.cat.get_default_workspace() neu = self.cat.create_workspace("neu", "http://example.com/neu") try: # make sure setting it works self.cat.set_default_workspace("neu") ws = self.cat.get_default_workspace() self.assertEqual('neu', ws.name) finally: # cleanup and reset to the way things were self.cat.delete(neu) self.cat.set_default_workspace(orig.name) ws = self.cat.get_default_workspace() self.assertEqual(orig.name, ws.name) def testFeatureTypeDelete(self): pass def testCoverageDelete(self): pass def testDataStoreDelete(self): states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == True) states.enabled = False self.assert_(states.enabled == False) self.cat.save(states) states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == False) states.enabled = True self.cat.save(states) states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == True) def testLayerGroupSave(self): tas = self.cat.get_layergroup("tasmania") self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers) self.assertEqual(tas.styles, [None, None, None, None], tas.styles) tas.layers = tas.layers[:-1] tas.styles = tas.styles[:-1] self.cat.save(tas) # this verifies the local state self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads'], tas.layers) self.assertEqual(tas.styles, [None, None, None], tas.styles) # force a refresh to check the remote state tas.refresh() self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads'], tas.layers) self.assertEqual(tas.styles, [None, None, None], tas.styles)
def _register_cascaded_layers(service, owner=None): """ Register layers for a cascading WMS """ if service.type == "WMS" or service.type == "OWS": cat = Catalog(settings.OGC_SERVER["default"]["LOCATION"] + "rest", _user, _password) # Can we always assume that it is geonode? # Should cascading layers have a separate workspace? cascade_ws = cat.get_workspace(service.name) if cascade_ws is None: cascade_ws = cat.create_workspace(service.name, "cascade") try: store = cat.get_store(service.name, cascade_ws) except Exception: store = cat.create_wmsstore(service.name, cascade_ws) cat.save(store) wms = WebMapService(service.base_url) layers = list(wms.contents) count = 0 for layer in layers: lyr = cat.get_resource(layer, store, cascade_ws) if lyr is None: if service.type in ["WMS", "OWS"]: resource = cat.create_wmslayer(cascade_ws, store, layer) elif service.type == "WFS": resource = cat.create_wfslayer(cascade_ws, store, layer) if resource: bbox = resource.latlon_bbox cascaded_layer, created = Layer.objects.get_or_create( typename="%s:%s" % (cascade_ws.name, resource.name), service=service, defaults={ "name": resource.name, "workspace": cascade_ws.name, "store": store.name, "storeType": store.resource_type, "title": resource.title or "No title provided", "abstract": resource.abstract or "No abstract provided", "owner": None, "uuid": str(uuid.uuid4()), "bbox_x0": bbox[0], "bbox_x1": bbox[1], "bbox_y0": bbox[2], "bbox_y1": bbox[3], }, ) if created: cascaded_layer.save() if cascaded_layer is not None and cascaded_layer.bbox is None: cascaded_layer._populate_from_gs(gs_resource=resource) cascaded_layer.set_default_permissions() service_layer, created = ServiceLayer.objects.get_or_create( service=service, typename=cascaded_layer.name ) service_layer.layer = cascaded_layer service_layer.title = (cascaded_layer.title,) service_layer.description = (cascaded_layer.abstract,) service_layer.styles = cascaded_layer.styles service_layer.save() count += 1 else: logger.error("Resource %s from store %s could not be saved as layer" % (layer, store.name)) message = "%d Layers Registered" % count return_dict = {"status": "ok", "msg": message} return HttpResponse(json.dumps(return_dict), mimetype="application/json", status=200) elif service.type == "WCS": return HttpResponse("Not Implemented (Yet)", status=501) else: return HttpResponse("Invalid Service Type", status=400)
def _register_cascaded_layers(service, owner=None): """ Register layers for a cascading WMS """ if service.type == 'WMS' or service.type == "OWS": cat = Catalog(settings.OGC_SERVER['default']['LOCATION'] + "rest", _user , _password) # Can we always assume that it is geonode? # Should cascading layers have a separate workspace? cascade_ws = cat.get_workspace(settings.CASCADE_WORKSPACE) if cascade_ws is None: cascade_ws = cat.create_workspace(settings.CASCADE_WORKSPACE, 'cascade') try: store = cat.get_store(service.name,cascade_ws) except Exception: store = cat.create_wmsstore(service.name, cascade_ws) wms = WebMapService(service.base_url) layers = list(wms.contents) count = 0 for layer in layers: lyr = cat.get_resource(layer, store, cascade_ws) if lyr is None: if service.type in ["WMS","OWS"]: resource = cat.create_wmslayer(cascade_ws, store, layer) elif service.type == "WFS": resource = cat.create_wfslayer(cascade_ws, store, layer) if resource: cascaded_layer, created = Layer.objects.get_or_create( typename = "%s:%s" % (cascade_ws.name, resource.name), defaults = { "name": resource.name, "workspace": cascade_ws.name, "store": store.name, "storeType": store.resource_type, "title": resource.title or 'No title provided', "abstract": resource.abstract or 'No abstract provided', "owner": None, "uuid": str(uuid.uuid4()) }) if created: cascaded_layer.save() if cascaded_layer is not None and cascaded_layer.bbox is None: cascaded_layer._populate_from_gs(gs_resource=resource) cascaded_layer.set_default_permissions() service_layer, created = ServiceLayer.objects.get_or_create( service=service, typename=cascaded_layer.name ) service_layer.layer = cascaded_layer service_layer.title=cascaded_layer.title, service_layer.description=cascaded_layer.abstract, service_layer.styles=cascaded_layer.styles service_layer.save() count += 1 else: logger.error("Resource %s from store %s could not be saved as layer" % (layer, store.name)) message = "%d Layers Registered" % count return_dict = {'status': 'ok', 'msg': message } return HttpResponse(json.dumps(return_dict), mimetype='application/json', status=200) elif service.type == 'WCS': return HttpResponse('Not Implemented (Yet)', status=501) else: return HttpResponse('Invalid Service Type', status=400)
class CatalogUtils: cat = None def __init__(self, url=None, user=None, pw=None): """ :param url: example: http://localhost:8080/geoserver/rest/ :param user: :param pw: """ self.cat = Catalog(url, username=user, password=pw) def ws(self, ws_name): return self.cat.get_workspace(ws_name) def get_shapefile(self, path): """ Creates a dictionary of all the files in a shapefile (.shp, .dbf, .xml, etc.) :param path: path to unarchived shapefile, without extension :return: """ return geoserver.util.shapefile_and_friends(path) def store_exists(self, name): for i in self.cat.get_stores(): if i.name == name: return True return False def add_shapefile(self, data, name=None, ws=None): """ Adds a shapefile to a GeoServer instance as a Feature Store :param data: the path to the shapefile (.shp) or the zipped shapefile (.zip) :param name: the name of the feature store. if None, the file name will be used :param ws: the name of the workspace. if None, the default workspace will be used :return: the created feature store """ if name is None: name = os.path.split(data)[-1] if name.endswith('.zip') or name.endswith('.shp'): name = name[:name.rindex('.')].upper() # name = name[:name.rindex('.')] print name if self.store_exists(name): print "Store exists", name raise Exception( "A store with this name already exists... please change the name." ) if data.endswith('.shp'): data = self.get_shapefile(data[:data.rindex('.')]) elif data.endswith('.zip'): pass else: raise Exception( "'data' must be the path to a shapefile (.shp) or zipped shapefile." ) if ws is not None: ws = self.ws(ws) if ws is None: raise Exception("The requested workspace does not exist.") else: ws = self.cat.get_default_workspace() if ws is None: raise Exception("No default workspace found!") print('adding: ' + name) self.cat.create_featurestore(name="GMU" + name, data=data, workspace=ws) return self.cat.get_store("GMU" + name)
from config import get_config from geoserver.catalog import Catalog geoserver = Catalog( get_config('geoserver.restUrl'), get_config('geoserver.user'), get_config('geoserver.password'), ) # create workspace if not exists, a workspace is mandatory to work with geoserver workspace_name = get_config('geoserver.workspace') workspace = geoserver.get_workspace(workspace_name) if workspace is None: geoserver.create_workspace( workspace_name, get_config('geoserver.hostUrl') + workspace_name) geoserver.reload() geoserver_connection = geoserver workspace_obj = workspace
class GeoGigUploaderBase(ImportHelper): def __init__(self, *args, **kwargs): super(GeoGigUploaderBase, self).__init__(*args, **kwargs) setUpModule() # this isn't available when being used in other module def setUp(self): self.admin_user = self.create_user('admin', 'admin', is_superuser=True) self.non_admin_user = self.create_user('non_admin', 'non_admin') self.catalog = Catalog(ogc_server_settings.internal_rest, *ogc_server_settings.credentials) if self.catalog.get_workspace('geonode') is None: self.catalog.create_workspace('geonode', 'http://www.geonode.org/') self.workspace = 'geonode' self.datastoreNames = [] def tearDown(self): """Clean up geoserver/geogig catalog. """ # delete stores (will cascade to delete layers) for store_name in self.datastoreNames: self.catalog.delete(self.catalog.get_store(store_name), recurse=True) # delete repository reference in geoserver for store_name in self.datastoreNames: self.remove_geogig_repo(store_name) # geoserver can leave connections open - HACK HACK HACK self.free_geogig_connections() # HACK HACK HACK -- sometimes connections from geoserver to geogig are left open. This kills the postgresql backend! # this is a major hammer. Once geoserver/geogig are better at cleaning up, remove this. def free_geogig_connections(self): with db.connections["geogig"].cursor() as c: c.execute( "select pg_terminate_backend(pid) from pg_stat_activity where application_name = 'PostgreSQL JDBC Driver' or application_name='geogig'" ) # aggressive delete of the repo (mostly cleans up after itself) # call the geogig rest API DELETE def remove_geogig_repo(self, ref_name): username = ogc_server_settings.credentials.username password = ogc_server_settings.credentials.password url = ogc_server_settings.rest http = httplib2.Http(disable_ssl_certificate_validation=False) http.add_credentials(username, password) netloc = urlparse(url).netloc http.authorizations.append( httplib2.BasicAuthentication((username, password), netloc, url, {}, None, None, http)) rest_url = ogc_server_settings.LOCATION + \ "geogig/repos/" + ref_name + "/delete.json" resp, content = http.request(rest_url, 'GET') response = json.loads(content) token = response["response"]["token"] rest_url = ogc_server_settings.LOCATION + \ "geogig/repos/" + ref_name + "?token=" + token resp, content = http.request(rest_url, 'DELETE') # convenience method to load in the test dataset # return a (geonode) layer # the layer will be in Geoserver and Geonode # self.catalog.get_layer(layer.name) -- to get the Geoserver Layer def fully_import_file(self, path, fname, start_time_column, end_time_column=None): # setup time if end_time_column is None: time_config = { 'convert_to_date': [start_time_column], 'start_date': start_time_column, 'configureTime': True } else: time_config = { 'convert_to_date': [start_time_column, end_time_column], 'start_date': start_time_column, 'end_date': end_time_column, 'configureTime': True } name = os.path.splitext(fname)[0] + "_" + str(uuid.uuid1())[:8] self.datastoreNames.append(name) # remember for future deletion full_fname = os.path.join(path, fname) configs = self.prepare_file_for_import(full_fname) configs[0].update({'name': name}) configs[0].update({'layer_name': name}) configs[0].update(time_config) # configure the datastore/repo configs[0]['geoserver_store'] = {} configs[0]['geoserver_store']['type'] = 'geogig' configs[0]['geoserver_store']['name'] = name configs[0]['geoserver_store']['create'] = 'true' configs[0]['geoserver_store']['branch'] = 'master' configs[0]['geoserver_store'][ 'geogig_repository'] = "geoserver://" + name result = self.generic_import(fname, path=path, configs=configs) return result def import_file(self, path, configs=None): """Imports the file. """ if configs is None: configs = [] self.assertTrue(os.path.exists(path), path) # run ogr2ogr ogr = OGRImport(path) layers = ogr.handle(configuration_options=configs) return layers def generic_import(self, filename, path, configs=None): if configs is None: configs = [{'index': 0}] path = os.path.join(path, filename) results = self.import_file(path, configs=configs) layer_results = [] for result in results: layer = Layer.objects.get(name=result[0]) self.assertEqual(layer.srid, 'EPSG:4326') self.assertTrue(layer.store in self.datastoreNames) self.assertEqual(layer.storeType, 'dataStore') if not path.endswith('zip'): self.assertGreaterEqual(layer.attributes.count(), DataSource(path)[0].num_fields) layer_results.append(layer) return layer_results[0] def prepare_file_for_import(self, filepath): """ Prepares the file path provided for import; performs some housekeeping, uploads & configures the file. Returns a list of dicts of the form {'index': <layer_index>, 'upload_layer_id': <upload_layer_id>} these may be used as configuration options for importing all of the layers in the file. """ # Make a copy of the test file, as it's removed in configure_upload() filename = os.path.basename(filepath) tmppath = os.path.join('/tmp', filename) shutil.copy(filepath, tmppath) # upload & configure_upload expect closed file objects # This is heritage from originally being closely tied to a view passing request.Files of = open(tmppath, 'rb') of.close() files = [of] uploaded_data = self.upload(files, self.admin_user) self.configure_upload(uploaded_data, files) configs = [{ 'index': l.index, 'upload_layer_id': l.id } for l in uploaded_data.uploadlayer_set.all()] return configs def create_user(self, username, password, **kwargs): """Convenience method for creating users. """ user, created = User.objects.get_or_create(username=username, **kwargs) if created: user.set_password(password) user.save() return user
class ModifyingTests(unittest.TestCase): def setUp(self): self.cat = Catalog("http://localhost:8080/geoserver/rest") def testFeatureTypeSave(self): # test saving round trip rs = self.cat.get_resource("bugsites") old_abstract = rs.abstract new_abstract = "Not the original abstract" enabled = rs.enabled # Change abstract on server rs.abstract = new_abstract self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(new_abstract, rs.abstract) self.assertEqual(enabled, rs.enabled) # Change keywords on server rs.keywords = ["bugsites", "gsconfig"] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(["bugsites", "gsconfig"], rs.keywords) self.assertEqual(enabled, rs.enabled) # Change metadata links on server rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual( [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")], rs.metadata_links) self.assertEqual(enabled, rs.enabled) # Restore abstract rs.abstract = old_abstract self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(old_abstract, rs.abstract) def testDataStoreCreate(self): ds = self.cat.create_datastore("vector_gsconfig") ds.connection_parameters.update( host="localhost", port="5432", database="db", user="******", passwd="password", dbtype="postgis") self.cat.save(ds) def testDataStoreModify(self): ds = self.cat.get_store("sf") self.assertFalse("foo" in ds.connection_parameters) ds.connection_parameters = ds.connection_parameters ds.connection_parameters["foo"] = "bar" orig_ws = ds.workspace.name self.cat.save(ds) ds = self.cat.get_store("sf") self.assertTrue("foo" in ds.connection_parameters) self.assertEqual("bar", ds.connection_parameters["foo"]) self.assertEqual(orig_ws, ds.workspace.name) def testDataStoreCreateAndThenAlsoImportData(self): ds = self.cat.create_datastore("gsconfig_import_test") ds.connection_parameters.update( host="localhost", port="5432", database="db", user="******", passwd="password", dbtype="postgis") self.cat.save(ds) ds = self.cat.get_store("gsconfig_import_test") self.cat.add_data_to_store(ds, "import", { 'shp': 'test/data/states.shp', 'shx': 'test/data/states.shx', 'dbf': 'test/data/states.dbf', 'prj': 'test/data/states.prj' }) def testCoverageStoreCreate(self): ds = self.cat.create_coveragestore2("coverage_gsconfig") ds.data_url = "file:data/mytiff.tiff" self.cat.save(ds) def testCoverageStoreModify(self): cs = self.cat.get_store("sfdem") self.assertEqual("GeoTIFF", cs.type) cs.type = "WorldImage" self.cat.save(cs) cs = self.cat.get_store("sfdem") self.assertEqual("WorldImage", cs.type) # not sure about order of test runs here, but it might cause problems # for other tests if this layer is misconfigured cs.type = "GeoTIFF" self.cat.save(cs) def testCoverageSave(self): # test saving round trip rs = self.cat.get_resource("Arc_Sample") old_abstract = rs.abstract new_abstract = "Not the original abstract" # # Change abstract on server rs.abstract = new_abstract self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual(new_abstract, rs.abstract) # Restore abstract rs.abstract = old_abstract self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual(old_abstract, rs.abstract) # Change metadata links on server rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual( [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")], rs.metadata_links) self.assertEqual(enabled, rs.enabled) srs_before = set(['EPSG:4326']) srs_after = set(['EPSG:4326', 'EPSG:3785']) formats = set(['ARCGRID', 'ARCGRID-GZIP', 'GEOTIFF', 'PNG', 'GIF', 'TIFF']) formats_after = set(["PNG", "GIF", "TIFF"]) # set and save request_srs_list self.assertEquals(set(rs.request_srs_list), srs_before, str(rs.request_srs_list)) rs.request_srs_list = rs.request_srs_list + ['EPSG:3785'] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.request_srs_list), srs_after, str(rs.request_srs_list)) # set and save response_srs_list self.assertEquals(set(rs.response_srs_list), srs_before, str(rs.response_srs_list)) rs.response_srs_list = rs.response_srs_list + ['EPSG:3785'] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.response_srs_list), srs_after, str(rs.response_srs_list)) # set and save supported_formats self.assertEquals(set(rs.supported_formats), formats, str(rs.supported_formats)) rs.supported_formats = ["PNG", "GIF", "TIFF"] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.supported_formats), formats_after, str(rs.supported_formats)) def testFeatureTypeCreate(self): shapefile_plus_sidecars = shapefile_and_friends("test/data/states") expected = { 'shp': 'test/data/states.shp', 'shx': 'test/data/states.shx', 'dbf': 'test/data/states.dbf', 'prj': 'test/data/states.prj' } self.assertEqual(len(expected), len(shapefile_plus_sidecars)) for k, v in expected.iteritems(): self.assertEqual(v, shapefile_plus_sidecars[k]) sf = self.cat.get_workspace("sf") self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf) self.assert_(self.cat.get_resource("states_test", workspace=sf) is not None) self.assertRaises( ConflictingDataError, lambda: self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf) ) self.assertRaises( UploadError, lambda: self.cat.create_coveragestore("states_raster_test", shapefile_plus_sidecars, sf) ) bogus_shp = { 'shp': 'test/data/Pk50095.tif', 'shx': 'test/data/Pk50095.tif', 'dbf': 'test/data/Pk50095.tfw', 'prj': 'test/data/Pk50095.prj' } self.assertRaises( UploadError, lambda: self.cat.create_featurestore("bogus_shp", bogus_shp, sf) ) lyr = self.cat.get_layer("states_test") self.cat.delete(lyr) self.assert_(self.cat.get_layer("states_test") is None) def testCoverageCreate(self): tiffdata = { 'tiff': 'test/data/Pk50095.tif', 'tfw': 'test/data/Pk50095.tfw', 'prj': 'test/data/Pk50095.prj' } sf = self.cat.get_workspace("sf") # TODO: Uploading WorldImage file no longer works??? # ft = self.cat.create_coveragestore("Pk50095", tiffdata, sf) # self.assert_(self.cat.get_resource("Pk50095", workspace=sf) is not None) # self.assertRaises( # ConflictingDataError, # lambda: self.cat.create_coveragestore("Pk50095", tiffdata, sf) # ) self.assertRaises( UploadError, lambda: self.cat.create_featurestore("Pk50095_vector", tiffdata, sf) ) bogus_tiff = { 'tiff': 'test/data/states.shp', 'tfw': 'test/data/states.shx', 'prj': 'test/data/states.prj' } self.assertRaises( UploadError, lambda: self.cat.create_coveragestore("states_raster", bogus_tiff) ) def testLayerSave(self): # test saving round trip lyr = self.cat.get_layer("states") old_attribution = lyr.attribution new_attribution = "Not the original attribution" # change attribution on server lyr.attribution = new_attribution self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(new_attribution, lyr.attribution) # Restore attribution lyr.attribution = old_attribution self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(old_attribution, lyr.attribution) self.assertEqual(lyr.default_style.name, "population") old_default_style = lyr.default_style lyr.default_style = (s for s in lyr.styles if s.name == "pophatch").next() lyr.styles = [old_default_style] self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(lyr.default_style.name, "pophatch") self.assertEqual([s.name for s in lyr.styles], ["population"]) def testStyles(self): # upload new style, verify existence self.cat.create_style("fred", open("test/fred.sld").read()) fred = self.cat.get_style("fred") self.assert_(fred is not None) self.assertEqual("Fred", fred.sld_title) # replace style, verify changes self.cat.create_style("fred", open("test/ted.sld").read(), overwrite=True) fred = self.cat.get_style("fred") self.assert_(fred is not None) self.assertEqual("Ted", fred.sld_title) # delete style, verify non-existence self.cat.delete(fred, purge=True) self.assert_(self.cat.get_style("fred") is None) # attempt creating new style self.cat.create_style("fred", open("test/fred.sld").read()) fred = self.cat.get_style("fred") self.assertEqual("Fred", fred.sld_title) def testWorkspaceCreate(self): ws = self.cat.get_workspace("acme") self.assertEqual(None, ws) self.cat.create_workspace("acme", "http://example.com/acme") ws = self.cat.get_workspace("acme") self.assertEqual("acme", ws.name) def testWorkspaceDelete(self): self.cat.create_workspace("foo", "http://example.com/foo") ws = self.cat.get_workspace("foo") self.cat.delete(ws) ws = self.cat.get_workspace("foo") self.assert_(ws is None) def testFeatureTypeDelete(self): pass def testCoverageDelete(self): pass def testDataStoreDelete(self): states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == True) states.enabled = False self.assert_(states.enabled == False) self.cat.save(states) states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == False) states.enabled = True self.cat.save(states) states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == True) def testLayerGroupSave(self): tas = self.cat.get_layergroup("tasmania") self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers) self.assertEqual(tas.styles, [None, None, None, None], tas.styles) tas.layers = tas.layers[:-1] tas.styles = tas.styles[:-1] self.cat.save(tas) self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads'], tas.layers) self.assertEqual(tas.styles, [None, None, None], tas.styles)
#sendToCatalog(catalog,sys.argv[1]) if __name__ == "__main__": if (len(sys.argv) != 4): print "Error with arguments. Must enter almost three" sys.exit(-1) print sys.argv[1] name_file = sys.argv[1].split("/")[-1] scenario = sys.argv[2] nameStore = sys.argv[3] cat = Catalog(geoserver_path) #pdb.set_trace() try: print name_file, sys.argv[1] vk = cat.get_workspace(scenario) if vk == None: vk = cat.create_workspace(scenario, scenario) vk.enabled = True try: cv = cat.create_coveragestore(nameStore, sys.argv[1], vk) inf = CoverageStore(cat, vk, scenario) inf.fetch() cat.save(inf) f.write("Processed %s" % (name_file)) except Exception: print "Catalogued %s!" % (name_file) print nameStore, name_file, scenario comman = 'curl -i --data "layerName=%s&coverageStore=%s&imageurl=ftp://131.254.204.143:21/../../usr/share/tomcat7/apache-tomcat-7.0.53/webapps/geoserver/data/data/%s/%s/%s.geotiff" http://172.18.242.41:8043/IDV' % ( name_file, nameStore, scenario, nameStore, nameStore) print comman
print 'USAGE: populate [GEOSERVER] [DBSERVER]' sys.exit(1) appserver = sys.argv[1] dbserver = sys.argv[2] ws_name = 'naturalearth' ds_name = 'ne_pg' lg_name = "ne_pg" cat = Catalog(appserver + '/rest') # check if workspace exists, bail if it does (safter than deleting it) if any(ws.name == ws_name for ws in cat.get_workspaces()): print 'workspace already exists...' ws = cat.get_workspace(ws_name) else: print 'creating workspace...' ws = cat.create_workspace(ws_name, 'http://www.naturalearth.org') if any(ds.workspace.name == ws.name and ds.name == ds_name for ds in cat.get_stores()): print 'datastore already exists...' ds = cat.get_store(ds_name, ws_name) else: print 'creating datastore' ds = cat.create_datastore(ds_name, ws.name) ds.connection_parameters.update( host=dbserver, port='5432', database='ne_tmp', user='******',
def publishGeoserver(appdef, progress): viewCrs = appdef["Settings"]["App view CRS"] usesGeoServer = False for applayer in appdef["Layers"]: if applayer.method != METHOD_FILE: if applayer.layer.type( ) == applayer.layer.VectorLayer and applayer.layer.providerType( ).lower() != "wfs": usesGeoServer = True if not usesGeoServer: return progress.setText("Publishing to GeoServer") progress.setProgress(0) geoserverUrl = appdef["Deploy"]["GeoServer url"] + "/rest" geoserverPassword = appdef["Deploy"]["GeoServer password"] geoserverUsername = appdef["Deploy"]["GeoServer username"] workspaceName = appdef["Deploy"]["GeoServer workspace"] dsName = "ds_" + workspaceName host = appdef["Deploy"]["PostGIS host"] port = appdef["Deploy"]["PostGIS port"] postgisUsername = appdef["Deploy"]["PostGIS username"] postgisPassword = appdef["Deploy"]["PostGIS password"] database = appdef["Deploy"]["PostGIS database"] schema = appdef["Deploy"]["PostGIS schema"] catalog = Catalog(geoserverUrl, geoserverUsername, geoserverPassword) workspace = catalog.get_workspace(workspaceName) if workspace is None: workspace = catalog.create_workspace(workspaceName, workspaceName) try: store = catalog.get_store(dsName, workspace) resources = store.get_resources() for resource in resources: layers = catalog.get_layers(resource) for layer in layers: catalog.delete(layer) catalog.delete(resource) catalog.delete(store) except Exception: pass try: store = catalog.get_store(dsName, workspace) except FailedRequestError: store = None for i, applayer in enumerate(appdef["Layers"]): layer = applayer.layer if applayer.method != METHOD_FILE and applayer.method != METHOD_DIRECT: name = safeName(layer.name()) sld, icons = getGsCompatibleSld(layer) if sld is not None: catalog.create_style(name, sld, True) uploadIcons(icons, geoserverUsername, geoserverPassword, catalog.gs_base_url) if layer.type() == layer.VectorLayer: if applayer.method == METHOD_WFS_POSTGIS or applayer.method == METHOD_WMS_POSTGIS: if store is None: store = catalog.create_datastore(dsName, workspace) store.connection_parameters.update( host=host, port=str(port), database=database, user=postgisUsername, schema=schema, passwd=postgisPassword, dbtype="postgis") catalog.save(store) catalog.publish_featuretype(name, store, layer.crs().authid()) else: path = getDataFromLayer(layer, viewCrs) catalog.create_featurestore(name, path, workspace=workspace, overwrite=True) gslayer = catalog.get_layer(name) r = gslayer.resource r.dirty['srs'] = viewCrs catalog.save(r) elif layer.type() == layer.RasterLayer: path = getDataFromLayer(layer, viewCrs) catalog.create_coveragestore(name, path, workspace=workspace, overwrite=True) if sld is not None: publishing = catalog.get_layer(name) publishing.default_style = catalog.get_style(name) catalog.save(publishing) progress.setProgress(int((i + 1) * 100.0 / len(appdef["Layers"])))
def publishGeoserver(appdef, progress): viewCrs = appdef["Settings"]["App view CRS"] usesGeoServer = False for applayer in appdef["Layers"]: if applayer.method != METHOD_FILE: if applayer.layer.type() == applayer.layer.VectorLayer and applayer.layer.providerType().lower() != "wfs": usesGeoServer = True if not usesGeoServer: return progress.setText("Publishing to GeoServer") progress.setProgress(0) geoserverUrl = appdef["Deploy"]["GeoServer url"] + "/rest" geoserverPassword = appdef["Deploy"]["GeoServer password"] geoserverUsername = appdef["Deploy"]["GeoServer username"] workspaceName = appdef["Deploy"]["GeoServer workspace"] dsName = "ds_" + workspaceName host = appdef["Deploy"]["PostGIS host"] port = appdef["Deploy"]["PostGIS port"] postgisUsername = appdef["Deploy"]["PostGIS username"] postgisPassword = appdef["Deploy"]["PostGIS password"] database = appdef["Deploy"]["PostGIS database"] schema = appdef["Deploy"]["PostGIS schema"] catalog = Catalog(geoserverUrl, geoserverUsername, geoserverPassword) workspace = catalog.get_workspace(workspaceName) if workspace is None: workspace = catalog.create_workspace(workspaceName, workspaceName) try: store = catalog.get_store(dsName, workspace) resources = store.get_resources() for resource in resources: layers = catalog.get_layers(resource) for layer in layers: catalog.delete(layer) catalog.delete(resource) catalog.delete(store) except Exception: pass try: store = catalog.get_store(dsName, workspace) except FailedRequestError: store = None for i, applayer in enumerate(appdef["Layers"]): layer = applayer.layer if applayer.method != METHOD_FILE and applayer.method != METHOD_DIRECT: name = safeName(layer.name()) sld, icons = getGsCompatibleSld(layer) if sld is not None: catalog.create_style(name, sld, True) uploadIcons(icons, geoserverUsername, geoserverPassword, catalog.gs_base_url) if layer.type() == layer.VectorLayer: if applayer.method == METHOD_WFS_POSTGIS or applayer.method == METHOD_WMS_POSTGIS: if store is None: store = catalog.create_datastore(dsName, workspace) store.connection_parameters.update( host=host, port=str(port), database=database, user=postgisUsername, schema=schema, passwd=postgisPassword, dbtype="postgis") catalog.save(store) catalog.publish_featuretype(name, store, layer.crs().authid()) else: path = getDataFromLayer(layer, viewCrs) catalog.create_featurestore(name, path, workspace=workspace, overwrite=True) gslayer = catalog.get_layer(name) r = gslayer.resource r.dirty['srs'] = viewCrs catalog.save(r) elif layer.type() == layer.RasterLayer: path = getDataFromLayer(layer, viewCrs) catalog.create_coveragestore(name, path, workspace=workspace, overwrite=True) if sld is not None: publishing = catalog.get_layer(name) publishing.default_style = catalog.get_style(name) catalog.save(publishing) progress.setProgress(int((i+1)*100.0/len(appdef["Layers"])))
from logging.handlers import RotatingFileHandler from os import path # Python 3 backported from collections import OrderedDict # 3rd party libraries from geoserver.catalog import Catalog from geoserver.resource import Coverage, FeatureType from geoserver.util import shapefile_and_friends # ############################################################################ # ########## MAIN ############# # ################################## # connection cat = Catalog("http://localhost:8080/geoserver/rest", "admin", "geoserver") # READ all_layers = cat.get_layers() print(len(all_layers)) # WRITE wks_esipe = cat.get_workspace("ESIPE_IG3") shapefile_plus_sidecars = shapefile_and_friends( r"data_samples\idf_RGP_emploi_exh") feat = cat.create_featurestore("test_gsoncif_write", workspace=wks_esipe, data=shapefile_plus_sidecars)
class ModifyingTests(unittest.TestCase): def setUp(self): self.cat = Catalog(GSPARAMS['GSURL'], username=GSPARAMS['GSUSER'], password=GSPARAMS['GSPASSWORD']) def testFeatureTypeSave(self): # test saving round trip rs = self.cat.get_resource("bugsites") old_abstract = rs.abstract new_abstract = "Not the original abstract" enabled = rs.enabled # Change abstract on server rs.abstract = new_abstract self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(new_abstract, rs.abstract) self.assertEqual(enabled, rs.enabled) # Change keywords on server rs.keywords = ["bugsites", "gsconfig"] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(["bugsites", "gsconfig"], rs.keywords) self.assertEqual(enabled, rs.enabled) # Change metadata links on server rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual( [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")], rs.metadata_links) self.assertEqual(enabled, rs.enabled) # Restore abstract rs.abstract = old_abstract self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(old_abstract, rs.abstract) def testDataStoreCreate(self): ds = self.cat.create_datastore("vector_gsconfig") ds.connection_parameters.update(**DBPARAMS) self.cat.save(ds) def testPublishFeatureType(self): # Use the other test and store creation to load vector data into a database # @todo maybe load directly to database? try: self.testDataStoreCreateAndThenAlsoImportData() except FailedRequestError: pass try: lyr = self.cat.get_layer('import') # Delete the existing layer and resource to allow republishing. self.cat.delete(lyr) self.cat.delete(lyr.resource) ds = self.cat.get_store("gsconfig_import_test") # make sure it's gone self.assert_(self.cat.get_layer('import') is None) self.cat.publish_featuretype("import", ds, native_crs="EPSG:4326") # and now it's not self.assert_(self.cat.get_layer('import') is not None) finally: # tear stuff down to allow the other test to pass if we run first ds = self.cat.get_store("gsconfig_import_test") lyr = self.cat.get_layer('import') # Delete the existing layer and resource to allow republishing. try: if lyr: self.cat.delete(lyr) self.cat.delete(lyr.resource) if ds: self.cat.delete(ds) except: pass def testDataStoreModify(self): ds = self.cat.get_store("sf") self.assertFalse("foo" in ds.connection_parameters) ds.connection_parameters = ds.connection_parameters ds.connection_parameters["foo"] = "bar" orig_ws = ds.workspace.name self.cat.save(ds) ds = self.cat.get_store("sf") self.assertTrue("foo" in ds.connection_parameters) self.assertEqual("bar", ds.connection_parameters["foo"]) self.assertEqual(orig_ws, ds.workspace.name) @drop_table('import') def testDataStoreCreateAndThenAlsoImportData(self): ds = self.cat.create_datastore("gsconfig_import_test") ds.connection_parameters.update(**DBPARAMS) self.cat.save(ds) ds = self.cat.get_store("gsconfig_import_test") self.cat.add_data_to_store(ds, "import", { 'shp': 'test/data/states.shp', 'shx': 'test/data/states.shx', 'dbf': 'test/data/states.dbf', 'prj': 'test/data/states.prj' }) @drop_table('import2') def testVirtualTables(self): ds = self.cat.create_datastore("gsconfig_import_test2") ds.connection_parameters.update(**DBPARAMS) self.cat.save(ds) ds = self.cat.get_store("gsconfig_import_test2") self.cat.add_data_to_store(ds, "import2", { 'shp': 'test/data/states.shp', 'shx': 'test/data/states.shx', 'dbf': 'test/data/states.dbf', 'prj': 'test/data/states.prj' }) store = self.cat.get_store("gsconfig_import_test2") geom = JDBCVirtualTableGeometry('the_geom','MultiPolygon','4326') ft_name = 'my_jdbc_vt_test' epsg_code = 'EPSG:4326' sql = "select * from import2 where 'STATE_NAME' = 'Illinois'" keyColumn = None parameters = None jdbc_vt = JDBCVirtualTable(ft_name, sql, 'false', geom, keyColumn, parameters) ft = self.cat.publish_featuretype(ft_name, store, epsg_code, jdbc_virtual_table=jdbc_vt) # DISABLED; this test works only in the very particular case # "mytiff.tiff" is already present into the GEOSERVER_DATA_DIR # def testCoverageStoreCreate(self): # ds = self.cat.create_coveragestore2("coverage_gsconfig") # ds.data_url = "file:test/data/mytiff.tiff" # self.cat.save(ds) def testCoverageStoreModify(self): cs = self.cat.get_store("sfdem") self.assertEqual("GeoTIFF", cs.type) cs.type = "WorldImage" self.cat.save(cs) cs = self.cat.get_store("sfdem") self.assertEqual("WorldImage", cs.type) # not sure about order of test runs here, but it might cause problems # for other tests if this layer is misconfigured cs.type = "GeoTIFF" self.cat.save(cs) def testCoverageSave(self): # test saving round trip rs = self.cat.get_resource("Arc_Sample") old_abstract = rs.abstract new_abstract = "Not the original abstract" # # Change abstract on server rs.abstract = new_abstract self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual(new_abstract, rs.abstract) # Restore abstract rs.abstract = old_abstract self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual(old_abstract, rs.abstract) # Change metadata links on server rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual( [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")], rs.metadata_links) self.assertEqual(enabled, rs.enabled) srs_before = set(['EPSG:4326']) srs_after = set(['EPSG:4326', 'EPSG:3785']) formats = set(['ARCGRID', 'ARCGRID-GZIP', 'GEOTIFF', 'PNG', 'GIF', 'TIFF']) formats_after = set(["PNG", "GIF", "TIFF"]) # set and save request_srs_list self.assertEquals(set(rs.request_srs_list), srs_before, str(rs.request_srs_list)) rs.request_srs_list = rs.request_srs_list + ['EPSG:3785'] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.request_srs_list), srs_after, str(rs.request_srs_list)) # set and save response_srs_list self.assertEquals(set(rs.response_srs_list), srs_before, str(rs.response_srs_list)) rs.response_srs_list = rs.response_srs_list + ['EPSG:3785'] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.response_srs_list), srs_after, str(rs.response_srs_list)) # set and save supported_formats self.assertEquals(set(rs.supported_formats), formats, str(rs.supported_formats)) rs.supported_formats = ["PNG", "GIF", "TIFF"] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.supported_formats), formats_after, str(rs.supported_formats)) def testWmsStoreCreate(self): ws = self.cat.create_wmsstore("wmsstore_gsconfig") ws.capabilitiesURL = "http://suite.opengeo.org/geoserver/ows?service=wms&version=1.1.1&request=GetCapabilities" ws.type = "WMS" self.cat.save(ws) def testWmsLayer(self): self.cat.create_workspace("wmstest", "http://example.com/wmstest") wmstest = self.cat.get_workspace("wmstest") wmsstore = self.cat.create_wmsstore("wmsstore", wmstest) wmsstore.capabilitiesURL = "http://suite.opengeo.org/geoserver/ows?service=wms&version=1.1.1&request=GetCapabilities" wmsstore.type = "WMS" self.cat.save(wmsstore) wmsstore = self.cat.get_store("wmsstore") self.assertEqual(1, len(self.cat.get_stores(wmstest))) available_layers = wmsstore.get_resources(available=True) for layer in available_layers: # sanitize the layer name - validation will fail on newer geoservers name = layer.replace(':', '_') new_layer = self.cat.create_wmslayer(wmstest, wmsstore, name, nativeName=layer) added_layers = wmsstore.get_resources() self.assertEqual(len(available_layers), len(added_layers)) changed_layer = added_layers[0] self.assertEqual(True, changed_layer.advertised) self.assertEqual(True, changed_layer.enabled) changed_layer.advertised = False changed_layer.enabled = False self.cat.save(changed_layer) self.cat._cache.clear() changed_layer = wmsstore.get_resources()[0] changed_layer.fetch() self.assertEqual(False, changed_layer.advertised) self.assertEqual(False, changed_layer.enabled) # Testing projection and projection policy changes changed_layer.projection = "EPSG:900913" changed_layer.projection_policy = "REPROJECT_TO_DECLARED" self.cat.save(changed_layer) self.cat._cache.clear() layer = self.cat.get_layer(changed_layer.name) self.assertEqual(layer.resource.projection_policy, changed_layer.projection_policy) self.assertEqual(layer.resource.projection, changed_layer.projection) def testFeatureTypeCreate(self): shapefile_plus_sidecars = shapefile_and_friends("test/data/states") expected = { 'shp': 'test/data/states.shp', 'shx': 'test/data/states.shx', 'dbf': 'test/data/states.dbf', 'prj': 'test/data/states.prj' } self.assertEqual(len(expected), len(shapefile_plus_sidecars)) for k, v in expected.iteritems(): self.assertEqual(v, shapefile_plus_sidecars[k]) sf = self.cat.get_workspace("sf") self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf) self.assert_(self.cat.get_resource("states_test", workspace=sf) is not None) self.assertRaises( ConflictingDataError, lambda: self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf) ) self.assertRaises( UploadError, lambda: self.cat.create_coveragestore("states_raster_test", shapefile_plus_sidecars, sf) ) bogus_shp = { 'shp': 'test/data/Pk50095.tif', 'shx': 'test/data/Pk50095.tif', 'dbf': 'test/data/Pk50095.tfw', 'prj': 'test/data/Pk50095.prj' } self.assertRaises( UploadError, lambda: self.cat.create_featurestore("bogus_shp", bogus_shp, sf) ) lyr = self.cat.get_layer("states_test") self.cat.delete(lyr) self.assert_(self.cat.get_layer("states_test") is None) def testCoverageCreate(self): tiffdata = { 'tiff': 'test/data/Pk50095.tif', 'tfw': 'test/data/Pk50095.tfw', 'prj': 'test/data/Pk50095.prj' } sf = self.cat.get_workspace("sf") ft = self.cat.create_coveragestore("Pk50095", tiffdata, sf) self.assert_(self.cat.get_resource("Pk50095", workspace=sf) is not None) self.assertRaises( ConflictingDataError, lambda: self.cat.create_coveragestore("Pk50095", tiffdata, sf) ) self.assertRaises( UploadError, lambda: self.cat.create_featurestore("Pk50095_vector", tiffdata, sf) ) bogus_tiff = { 'tiff': 'test/data/states.shp', 'tfw': 'test/data/states.shx', 'prj': 'test/data/states.prj' } self.assertRaises( UploadError, lambda: self.cat.create_coveragestore("states_raster", bogus_tiff) ) ft_ext = self.cat.create_coveragestore_external_geotiff("Pk50095_ext", 'file:test/data/Pk50095.tif', sf) def testLayerSave(self): # test saving round trip lyr = self.cat.get_layer("states") old_attribution = lyr.attribution new_attribution = { 'title': 'Not the original attribution', 'width': '123', 'height': '321', 'href': 'http://www.georchestra.org', 'url': 'https://www.cigalsace.org/portail/cigal/documents/page/mentions-legales/Logo_geOrchestra.jpg', 'type': 'image/jpeg' } # change attribution on server lyr.attribution = new_attribution self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(new_attribution, lyr.attribution) # Restore attribution lyr.attribution = old_attribution self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(old_attribution, lyr.attribution) self.assertEqual(lyr.default_style.name, "population") old_default_style = lyr.default_style lyr.default_style = (s for s in lyr.styles if s.name == "pophatch").next() lyr.styles = [old_default_style] self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(lyr.default_style.name, "pophatch") self.assertEqual([s.name for s in lyr.styles], ["population"]) def testStyles(self): # check count before tests (upload) count = len(self.cat.get_styles()) # upload new style, verify existence self.cat.create_style("fred", open("test/fred.sld").read()) fred = self.cat.get_style("fred") self.assert_(fred is not None) self.assertEqual("Fred", fred.sld_title) # replace style, verify changes self.cat.create_style("fred", open("test/ted.sld").read(), overwrite=True) fred = self.cat.get_style("fred") self.assert_(fred is not None) self.assertEqual("Ted", fred.sld_title) # delete style, verify non-existence self.cat.delete(fred, purge=True) self.assert_(self.cat.get_style("fred") is None) # attempt creating new style self.cat.create_style("fred", open("test/fred.sld").read()) fred = self.cat.get_style("fred") self.assertEqual("Fred", fred.sld_title) # verify it can be found via URL and check the name f = self.cat.get_style_by_url(fred.href) self.assert_(f is not None) self.assertEqual(f.name, fred.name) # compare count after upload self.assertEqual(count +1, len(self.cat.get_styles())) # attempt creating a new style without "title" self.cat.create_style("notitle", open("test/notitle.sld").read()) notitle = self.cat.get_style("notitle") self.assertEqual(None, notitle.sld_title) def testWorkspaceStyles(self): # upload new style, verify existence self.cat.create_style("jed", open("test/fred.sld").read(), workspace="topp") jed = self.cat.get_style("jed", workspace="blarny") self.assert_(jed is None) jed = self.cat.get_style("jed", workspace="topp") self.assert_(jed is not None) self.assertEqual("Fred", jed.sld_title) jed = self.cat.get_style("topp:jed") self.assert_(jed is not None) self.assertEqual("Fred", jed.sld_title) # replace style, verify changes self.cat.create_style("jed", open("test/ted.sld").read(), overwrite=True, workspace="topp") jed = self.cat.get_style("jed", workspace="topp") self.assert_(jed is not None) self.assertEqual("Ted", jed.sld_title) # delete style, verify non-existence self.cat.delete(jed, purge=True) self.assert_(self.cat.get_style("jed", workspace="topp") is None) # attempt creating new style self.cat.create_style("jed", open("test/fred.sld").read(), workspace="topp") jed = self.cat.get_style("jed", workspace="topp") self.assertEqual("Fred", jed.sld_title) # verify it can be found via URL and check the full name f = self.cat.get_style_by_url(jed.href) self.assert_(f is not None) self.assertEqual(f.fqn, jed.fqn) def testLayerWorkspaceStyles(self): # upload new style, verify existence self.cat.create_style("ned", open("test/fred.sld").read(), overwrite=True, workspace="topp") self.cat.create_style("zed", open("test/ted.sld").read(), overwrite=True, workspace="topp") ned = self.cat.get_style("ned", workspace="topp") zed = self.cat.get_style("zed", workspace="topp") self.assert_(ned is not None) self.assert_(zed is not None) lyr = self.cat.get_layer("states") lyr.default_style = ned lyr.styles = [zed] self.cat.save(lyr) self.assertEqual("topp:ned", lyr.default_style) self.assertEqual([zed], lyr.styles) lyr.refresh() self.assertEqual("topp:ned", lyr.default_style.fqn) self.assertEqual([zed.fqn], [s.fqn for s in lyr.styles]) def testWorkspaceCreate(self): ws = self.cat.get_workspace("acme") self.assertEqual(None, ws) self.cat.create_workspace("acme", "http://example.com/acme") ws = self.cat.get_workspace("acme") self.assertEqual("acme", ws.name) def testWorkspaceDelete(self): self.cat.create_workspace("foo", "http://example.com/foo") ws = self.cat.get_workspace("foo") self.cat.delete(ws) ws = self.cat.get_workspace("foo") self.assert_(ws is None) def testWorkspaceDefault(self): # save orig orig = self.cat.get_default_workspace() neu = self.cat.create_workspace("neu", "http://example.com/neu") try: # make sure setting it works self.cat.set_default_workspace("neu") ws = self.cat.get_default_workspace() self.assertEqual('neu', ws.name) finally: # cleanup and reset to the way things were self.cat.delete(neu) self.cat.set_default_workspace(orig.name) ws = self.cat.get_default_workspace() self.assertEqual(orig.name, ws.name) def testFeatureTypeDelete(self): pass def testCoverageDelete(self): pass def testDataStoreDelete(self): states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == True) states.enabled = False self.assert_(states.enabled == False) self.cat.save(states) states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == False) states.enabled = True self.cat.save(states) states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == True) def testLayerGroupSave(self): tas = self.cat.get_layergroup("tasmania") self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers) self.assertEqual(tas.styles, [None, None, None, None], tas.styles) tas.layers = tas.layers[:-1] tas.styles = tas.styles[:-1] self.cat.save(tas) # this verifies the local state self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads'], tas.layers) self.assertEqual(tas.styles, [None, None, None], tas.styles) # force a refresh to check the remote state tas.refresh() self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads'], tas.layers) self.assertEqual(tas.styles, [None, None, None], tas.styles) def testImageMosaic(self): """ Test case for Issue #110 """ # testing the mosaic creation name = 'cea_mosaic' data = open('test/data/mosaic/cea.zip', 'rb') self.cat.create_imagemosaic(name, data) # get the layer resource back self.cat._cache.clear() resource = self.cat.get_layer(name).resource self.assert_(resource is not None) # delete granule from mosaic coverage = name store = self.cat.get_store(name) granule_id = name + '.1' self.cat.mosaic_delete_granule(coverage, store, granule_id) def testTimeDimension(self): sf = self.cat.get_workspace("sf") files = shapefile_and_friends(os.path.join(gisdata.GOOD_DATA, "time", "boxes_with_end_date")) self.cat.create_featurestore("boxes_with_end_date", files, sf) get_resource = lambda: self.cat._cache.clear() or self.cat.get_layer('boxes_with_end_date').resource # configure time as LIST resource = get_resource() timeInfo = DimensionInfo("time", "true", "LIST", None, "ISO8601", None, attribute="date") resource.metadata = {'time':timeInfo} self.cat.save(resource) # and verify resource = get_resource() timeInfo = resource.metadata['time'] self.assertEqual("LIST", timeInfo.presentation) self.assertEqual(True, timeInfo.enabled) self.assertEqual("date", timeInfo.attribute) self.assertEqual("ISO8601", timeInfo.units) # disable time dimension timeInfo = resource.metadata['time'] timeInfo.enabled = False # since this is an xml property, it won't get written unless we modify it resource.metadata = {'time' : timeInfo} self.cat.save(resource) # and verify resource = get_resource() timeInfo = resource.metadata['time'] self.assertEqual(False, timeInfo.enabled) # configure with interval, end_attribute and enable again timeInfo.enabled = True timeInfo.presentation = 'DISCRETE_INTERVAL' timeInfo.resolution = '3 days' timeInfo.end_attribute = 'enddate' resource.metadata = {'time' : timeInfo} self.cat.save(resource) # and verify resource = get_resource() timeInfo = resource.metadata['time'] self.assertEqual(True, timeInfo.enabled) self.assertEqual('DISCRETE_INTERVAL', timeInfo.presentation) self.assertEqual('3 days', timeInfo.resolution_str()) self.assertEqual('enddate', timeInfo.end_attribute)
auth=('admin', 'geoserver1'), data=payload, headers=headers) layerurl = '%s/geoserver/rest/layers/%s' % (geoserverurl, layername) layerheaders = {'Content-type': 'application/json'} jsonstr = {'layer': {'defaultStyle': {'name': layername}}} layerpayload = json.dumps(jsonstr) layerresp = requests.put(layerurl, auth=(user, pw), data=layerpayload, headers=layerheaders) # pubilsh grouplayers geourl = "%s/geoserver/rest/" % (geoserverurl) # the url of geoserver geocat = Catalog(geourl, user, pw) # create a Catalog object workspace = geocat.get_workspace(targeworkspace) # workspace name layers = geocat.get_layers() lys = [] for layer in layersconfig: size = len(targeworkspace) + 1 isingeoserver = False if (layernames.__contains__(layer)): for geoserverlyr in layers: if geoserverlyr.name[size:] == layer: isingeoserver = True lys.append(targeworkspace + ":" + layer) break else: print(layer + " not in slds!!") if not isingeoserver: print(layer + " not in geoserver!!")
def _register_cascaded_service(url, type, name, username, password, wms=None, owner=None, parent=None): """ Register a service as cascading WMS """ try: service = Service.objects.get(base_url=url) return_dict = {} return_dict["service_id"] = service.pk return_dict["msg"] = "This is an existing Service" return HttpResponse(json.dumps(return_dict), mimetype="application/json", status=200) except: # TODO: Handle this error properly pass if wms is None: wms = WebMapService(url) # TODO: Make sure we are parsing all service level metadata # TODO: Handle for setting ServiceProfiletRole service = Service.objects.create( base_url=url, type=type, method="C", name=name, version=wms.identification.version, title=wms.identification.title, abstract=wms.identification.abstract, online_resource=wms.provider.url, owner=owner, parent=parent, ) service.keywords = ",".join(wms.identification.keywords) service.save() service.set_default_permissions() if type in ["WMS", "OWS"]: # Register the Service with GeoServer to be cascaded cat = Catalog(settings.OGC_SERVER["default"]["LOCATION"] + "rest", _user, _password) cascade_ws = cat.get_workspace(name) if cascade_ws is None: cascade_ws = cat.create_workspace(name, "http://geonode.org/" + name) # TODO: Make sure there isn't an existing store with that name, and # deal with it if there is try: cascade_store = cat.get_store(name, cascade_ws) except: cascade_store = cat.create_wmsstore(name, cascade_ws, username, password) cascade_store.capabilitiesURL = url cascade_store.type = "WMS" cat.save(cascade_store) available_resources = cascade_store.get_resources(available=True) elif type == "WFS": # Register the Service with GeoServer to be cascaded cat = Catalog(settings.OGC_SERVER["default"]["LOCATION"] + "rest", _user, _password) # Can we always assume that it is geonode? cascade_ws = cat.get_workspace(settings.CASCADE_WORKSPACE) if cascade_ws is None: cascade_ws = cat.create_workspace(settings.CASCADE_WORKSPACE, "http://geonode.org/cascade") try: wfs_ds = cat.get_store(name, cascade_ws) except: wfs_ds = cat.create_datastore(name, cascade_ws) connection_params = { "WFSDataStoreFactory:MAXFEATURES": "0", "WFSDataStoreFactory:TRY_GZIP": "true", "WFSDataStoreFactory:PROTOCOL": "false", "WFSDataStoreFactory:LENIENT": "true", "WFSDataStoreFactory:TIMEOUT": "3000", "WFSDataStoreFactory:BUFFER_SIZE": "10", "WFSDataStoreFactory:ENCODING": "UTF-8", "WFSDataStoreFactory:WFS_STRATEGY": "nonstrict", "WFSDataStoreFactory:GET_CAPABILITIES_URL": url, } if username and password: connection_params["WFSDataStoreFactory:USERNAME"] = username connection_params["WFSDataStoreFactory:PASSWORD"] = password wfs_ds.connection_parameters = connection_params cat.save(wfs_ds) available_resources = wfs_ds.get_resources(available=True) # Save the Service record service, created = Service.objects.get_or_create(type=type, method="C", base_url=url, name=name, owner=owner) service.save() service.set_default_permissions() elif type == "WCS": return HttpResponse("Not Implemented (Yet)", status=501) else: return HttpResponse( "Invalid Method / Type combo: " + "Only Cascaded WMS, WFS and WCS supported", mimetype="text/plain", status=400, ) message = "Service %s registered" % service.name return_dict = [ { "status": "ok", "msg": message, "service_id": service.pk, "service_name": service.name, "service_title": service.title, "available_layers": available_resources, } ] if settings.USE_QUEUE: # Create a layer import job WebServiceHarvestLayersJob.objects.get_or_create(service=service) else: _register_cascaded_layers(service) return HttpResponse(json.dumps(return_dict), mimetype="application/json", status=200)
class ModifyingTests(unittest.TestCase): def setUp(self): self.cat = Catalog("http://localhost:8080/geoserver/rest") def testFeatureTypeSave(self): # test saving round trip rs = self.cat.get_resource("bugsites") old_abstract = rs.abstract new_abstract = "Not the original abstract" enabled = rs.enabled # Change abstract on server rs.abstract = new_abstract self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(new_abstract, rs.abstract) self.assertEqual(enabled, rs.enabled) # Change keywords on server rs.keywords = ["bugsites", "gsconfig"] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(["bugsites", "gsconfig"], rs.keywords) self.assertEqual(enabled, rs.enabled) # Change metadata links on server rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual( [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")], rs.metadata_links) self.assertEqual(enabled, rs.enabled) # Restore abstract rs.abstract = old_abstract self.cat.save(rs) rs = self.cat.get_resource("bugsites") self.assertEqual(old_abstract, rs.abstract) def testDataStoreCreate(self): ds = self.cat.create_datastore("vector_gsconfig") ds.connection_parameters.update(**DBPARAMS) self.cat.save(ds) def testPublishFeatureType(self): # Use the other test and store creation to load vector data into a database # @todo maybe load directly to database? try: self.testDataStoreCreateAndThenAlsoImportData() except FailedRequestError: pass try: lyr = self.cat.get_layer('import') # Delete the existing layer and resource to allow republishing. self.cat.delete(lyr) self.cat.delete(lyr.resource) ds = self.cat.get_store("gsconfig_import_test") # make sure it's gone self.assert_(self.cat.get_layer('import') is None) self.cat.publish_featuretype("import", ds, native_crs="EPSG:4326") # and now it's not self.assert_(self.cat.get_layer('import') is not None) finally: # tear stuff down to allow the other test to pass if we run first ds = self.cat.get_store("gsconfig_import_test") lyr = self.cat.get_layer('import') # Delete the existing layer and resource to allow republishing. self.cat.delete(lyr) self.cat.delete(lyr.resource) self.cat.delete(ds) def testDataStoreModify(self): ds = self.cat.get_store("sf") self.assertFalse("foo" in ds.connection_parameters) ds.connection_parameters = ds.connection_parameters ds.connection_parameters["foo"] = "bar" orig_ws = ds.workspace.name self.cat.save(ds) ds = self.cat.get_store("sf") self.assertTrue("foo" in ds.connection_parameters) self.assertEqual("bar", ds.connection_parameters["foo"]) self.assertEqual(orig_ws, ds.workspace.name) @drop_table('import') def testDataStoreCreateAndThenAlsoImportData(self): ds = self.cat.create_datastore("gsconfig_import_test") ds.connection_parameters.update(**DBPARAMS) self.cat.save(ds) ds = self.cat.get_store("gsconfig_import_test") self.cat.add_data_to_store(ds, "import", { 'shp': 'test/data/states.shp', 'shx': 'test/data/states.shx', 'dbf': 'test/data/states.dbf', 'prj': 'test/data/states.prj' }) def testCoverageStoreCreate(self): ds = self.cat.create_coveragestore2("coverage_gsconfig") ds.data_url = "file:data/mytiff.tiff" self.cat.save(ds) def testCoverageStoreModify(self): cs = self.cat.get_store("sfdem") self.assertEqual("GeoTIFF", cs.type) cs.type = "WorldImage" self.cat.save(cs) cs = self.cat.get_store("sfdem") self.assertEqual("WorldImage", cs.type) # not sure about order of test runs here, but it might cause problems # for other tests if this layer is misconfigured cs.type = "GeoTIFF" self.cat.save(cs) def testCoverageSave(self): # test saving round trip rs = self.cat.get_resource("Arc_Sample") old_abstract = rs.abstract new_abstract = "Not the original abstract" # # Change abstract on server rs.abstract = new_abstract self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual(new_abstract, rs.abstract) # Restore abstract rs.abstract = old_abstract self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual(old_abstract, rs.abstract) # Change metadata links on server rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")] enabled = rs.enabled self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEqual( [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")], rs.metadata_links) self.assertEqual(enabled, rs.enabled) srs_before = set(['EPSG:4326']) srs_after = set(['EPSG:4326', 'EPSG:3785']) formats = set(['ARCGRID', 'ARCGRID-GZIP', 'GEOTIFF', 'PNG', 'GIF', 'TIFF']) formats_after = set(["PNG", "GIF", "TIFF"]) # set and save request_srs_list self.assertEquals(set(rs.request_srs_list), srs_before, str(rs.request_srs_list)) rs.request_srs_list = rs.request_srs_list + ['EPSG:3785'] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.request_srs_list), srs_after, str(rs.request_srs_list)) # set and save response_srs_list self.assertEquals(set(rs.response_srs_list), srs_before, str(rs.response_srs_list)) rs.response_srs_list = rs.response_srs_list + ['EPSG:3785'] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.response_srs_list), srs_after, str(rs.response_srs_list)) # set and save supported_formats self.assertEquals(set(rs.supported_formats), formats, str(rs.supported_formats)) rs.supported_formats = ["PNG", "GIF", "TIFF"] self.cat.save(rs) rs = self.cat.get_resource("Arc_Sample") self.assertEquals(set(rs.supported_formats), formats_after, str(rs.supported_formats)) def testWmsStoreCreate(self): ws = self.cat.create_wmsstore("wmsstore_gsconfig") ws.capabilitiesURL = "http://suite.opengeo.org/geoserver/ows?service=wms&version=1.1.1&request=GetCapabilities" ws.type = "WMS" self.cat.save(ws) def testWmsLayer(self): self.cat.create_workspace("wmstest", "http://example.com/wmstest") wmstest = self.cat.get_workspace("wmstest") wmsstore = self.cat.create_wmsstore("wmsstore", wmstest) wmsstore.capabilitiesURL = "http://suite.opengeo.org/geoserver/ows?service=wms&version=1.1.1&request=GetCapabilities" wmsstore.type = "WMS" self.cat.save(wmsstore) wmsstore = self.cat.get_store("wmsstore") self.assertEqual(1, len(self.cat.get_stores(wmstest))) available_layers = wmsstore.get_resources(available=True) for layer in available_layers: # sanitize the layer name - validation will fail on newer geoservers name = layer.replace(':', '_') new_layer = self.cat.create_wmslayer(wmstest, wmsstore, name, nativeName=layer) added_layers = wmsstore.get_resources() self.assertEqual(len(available_layers), len(added_layers)) changed_layer = added_layers[0] self.assertEqual(True, changed_layer.advertised) self.assertEqual(True, changed_layer.enabled) changed_layer.advertised = False changed_layer.enabled = False self.cat.save(changed_layer) self.cat._cache.clear() changed_layer = wmsstore.get_resources()[0] changed_layer.fetch() self.assertEqual(False, changed_layer.advertised) self.assertEqual(False, changed_layer.enabled) def testFeatureTypeCreate(self): shapefile_plus_sidecars = shapefile_and_friends("test/data/states") expected = { 'shp': 'test/data/states.shp', 'shx': 'test/data/states.shx', 'dbf': 'test/data/states.dbf', 'prj': 'test/data/states.prj' } self.assertEqual(len(expected), len(shapefile_plus_sidecars)) for k, v in expected.iteritems(): self.assertEqual(v, shapefile_plus_sidecars[k]) sf = self.cat.get_workspace("sf") self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf) self.assert_(self.cat.get_resource("states_test", workspace=sf) is not None) self.assertRaises( ConflictingDataError, lambda: self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf) ) self.assertRaises( UploadError, lambda: self.cat.create_coveragestore("states_raster_test", shapefile_plus_sidecars, sf) ) bogus_shp = { 'shp': 'test/data/Pk50095.tif', 'shx': 'test/data/Pk50095.tif', 'dbf': 'test/data/Pk50095.tfw', 'prj': 'test/data/Pk50095.prj' } self.assertRaises( UploadError, lambda: self.cat.create_featurestore("bogus_shp", bogus_shp, sf) ) lyr = self.cat.get_layer("states_test") self.cat.delete(lyr) self.assert_(self.cat.get_layer("states_test") is None) def testCoverageCreate(self): tiffdata = { 'tiff': 'test/data/Pk50095.tif', 'tfw': 'test/data/Pk50095.tfw', 'prj': 'test/data/Pk50095.prj' } sf = self.cat.get_workspace("sf") # TODO: Uploading WorldImage file no longer works??? # ft = self.cat.create_coveragestore("Pk50095", tiffdata, sf) # self.assert_(self.cat.get_resource("Pk50095", workspace=sf) is not None) # self.assertRaises( # ConflictingDataError, # lambda: self.cat.create_coveragestore("Pk50095", tiffdata, sf) # ) self.assertRaises( UploadError, lambda: self.cat.create_featurestore("Pk50095_vector", tiffdata, sf) ) bogus_tiff = { 'tiff': 'test/data/states.shp', 'tfw': 'test/data/states.shx', 'prj': 'test/data/states.prj' } self.assertRaises( UploadError, lambda: self.cat.create_coveragestore("states_raster", bogus_tiff) ) def testLayerSave(self): # test saving round trip lyr = self.cat.get_layer("states") old_attribution = lyr.attribution new_attribution = "Not the original attribution" # change attribution on server lyr.attribution = new_attribution self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(new_attribution, lyr.attribution) # Restore attribution lyr.attribution = old_attribution self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(old_attribution, lyr.attribution) self.assertEqual(lyr.default_style.name, "population") old_default_style = lyr.default_style lyr.default_style = (s for s in lyr.styles if s.name == "pophatch").next() lyr.styles = [old_default_style] self.cat.save(lyr) lyr = self.cat.get_layer("states") self.assertEqual(lyr.default_style.name, "pophatch") self.assertEqual([s.name for s in lyr.styles], ["population"]) def testStyles(self): # upload new style, verify existence self.cat.create_style("fred", open("test/fred.sld").read()) fred = self.cat.get_style("fred") self.assert_(fred is not None) self.assertEqual("Fred", fred.sld_title) # replace style, verify changes self.cat.create_style("fred", open("test/ted.sld").read(), overwrite=True) fred = self.cat.get_style("fred") self.assert_(fred is not None) self.assertEqual("Ted", fred.sld_title) # delete style, verify non-existence self.cat.delete(fred, purge=True) self.assert_(self.cat.get_style("fred") is None) # attempt creating new style self.cat.create_style("fred", open("test/fred.sld").read()) fred = self.cat.get_style("fred") self.assertEqual("Fred", fred.sld_title) # verify it can be found via URL and check the name f = self.cat.get_style_by_url(fred.href) self.assert_(f is not None) self.assertEqual(f.name, fred.name) def testWorkspaceStyles(self): # upload new style, verify existence self.cat.create_style("jed", open("test/fred.sld").read(), workspace="topp") jed = self.cat.get_style("jed", workspace="blarny") self.assert_(jed is None) jed = self.cat.get_style("jed", workspace="topp") self.assert_(jed is not None) self.assertEqual("Fred", jed.sld_title) jed = self.cat.get_style("topp:jed") self.assert_(jed is not None) self.assertEqual("Fred", jed.sld_title) # replace style, verify changes self.cat.create_style("jed", open("test/ted.sld").read(), overwrite=True, workspace="topp") jed = self.cat.get_style("jed", workspace="topp") self.assert_(jed is not None) self.assertEqual("Ted", jed.sld_title) # delete style, verify non-existence self.cat.delete(jed, purge=True) self.assert_(self.cat.get_style("jed", workspace="topp") is None) # attempt creating new style self.cat.create_style("jed", open("test/fred.sld").read(), workspace="topp") jed = self.cat.get_style("jed", workspace="topp") self.assertEqual("Fred", jed.sld_title) # verify it can be found via URL and check the full name f = self.cat.get_style_by_url(jed.href) self.assert_(f is not None) self.assertEqual(f.fqn, jed.fqn) def testLayerWorkspaceStyles(self): # upload new style, verify existence self.cat.create_style("ned", open("test/fred.sld").read(), overwrite=True, workspace="topp") self.cat.create_style("zed", open("test/ted.sld").read(), overwrite=True, workspace="topp") ned = self.cat.get_style("ned", workspace="topp") zed = self.cat.get_style("zed", workspace="topp") self.assert_(ned is not None) self.assert_(zed is not None) lyr = self.cat.get_layer("states") lyr.default_style = ned lyr.styles = [zed] self.cat.save(lyr) self.assertEqual("topp:ned", lyr.default_style) self.assertEqual([zed], lyr.styles) lyr.refresh() self.assertEqual("topp:ned", lyr.default_style.fqn) self.assertEqual([zed.fqn], [s.fqn for s in lyr.styles]) def testWorkspaceCreate(self): ws = self.cat.get_workspace("acme") self.assertEqual(None, ws) self.cat.create_workspace("acme", "http://example.com/acme") ws = self.cat.get_workspace("acme") self.assertEqual("acme", ws.name) def testWorkspaceDelete(self): self.cat.create_workspace("foo", "http://example.com/foo") ws = self.cat.get_workspace("foo") self.cat.delete(ws) ws = self.cat.get_workspace("foo") self.assert_(ws is None) def testWorkspaceDefault(self): # save orig orig = self.cat.get_default_workspace() neu = self.cat.create_workspace("neu", "http://example.com/neu") try: # make sure setting it works self.cat.set_default_workspace("neu") ws = self.cat.get_default_workspace() self.assertEqual('neu', ws.name) finally: # cleanup and reset to the way things were self.cat.delete(neu) self.cat.set_default_workspace(orig.name) ws = self.cat.get_default_workspace() self.assertEqual(orig.name, ws.name) def testFeatureTypeDelete(self): pass def testCoverageDelete(self): pass def testDataStoreDelete(self): states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == True) states.enabled = False self.assert_(states.enabled == False) self.cat.save(states) states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == False) states.enabled = True self.cat.save(states) states = self.cat.get_store('states_shapefile') self.assert_(states.enabled == True) def testLayerGroupSave(self): tas = self.cat.get_layergroup("tasmania") self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers) self.assertEqual(tas.styles, [None, None, None, None], tas.styles) tas.layers = tas.layers[:-1] tas.styles = tas.styles[:-1] self.cat.save(tas) # this verifies the local state self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads'], tas.layers) self.assertEqual(tas.styles, [None, None, None], tas.styles) # force a refresh to check the remote state tas.refresh() self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads'], tas.layers) self.assertEqual(tas.styles, [None, None, None], tas.styles) def testTimeDimension(self): sf = self.cat.get_workspace("sf") files = shapefile_and_friends(os.path.join(gisdata.GOOD_DATA, "time", "boxes_with_end_date")) self.cat.create_featurestore("boxes_with_end_date", files, sf) get_resource = lambda: self.cat._cache.clear() or self.cat.get_layer('boxes_with_end_date').resource # configure time as LIST resource = get_resource() timeInfo = DimensionInfo("time", "true", "LIST", None, "ISO8601", None, attribute="date") resource.metadata = {'time':timeInfo} self.cat.save(resource) # and verify resource = get_resource() timeInfo = resource.metadata['time'] self.assertEqual("LIST", timeInfo.presentation) self.assertEqual(True, timeInfo.enabled) self.assertEqual("date", timeInfo.attribute) self.assertEqual("ISO8601", timeInfo.units) # disable time dimension timeInfo = resource.metadata['time'] timeInfo.enabled = False # since this is an xml property, it won't get written unless we modify it resource.metadata = {'time' : timeInfo} self.cat.save(resource) # and verify resource = get_resource() timeInfo = resource.metadata['time'] self.assertEqual(False, timeInfo.enabled) # configure with interval, end_attribute and enable again timeInfo.enabled = True timeInfo.presentation = 'DISCRETE_INTERVAL' timeInfo.resolution = '3 days' timeInfo.end_attribute = 'enddate' resource.metadata = {'time' : timeInfo} self.cat.save(resource) # and verify resource = get_resource() timeInfo = resource.metadata['time'] self.assertEqual(True, timeInfo.enabled) self.assertEqual('DISCRETE_INTERVAL', timeInfo.presentation) self.assertEqual('3 days', timeInfo.resolution_str()) self.assertEqual('enddate', timeInfo.end_attribute)
def gs_slurp(ignore_errors=True, verbosity=1, console=None, owner=None, workspace=None, store=None, filter=None): """Configure the layers available in GeoServer in GeoNode. It returns a list of dictionaries with the name of the layer, the result of the operation and the errors and traceback if it failed. """ if console is None: console = open(os.devnull, 'w') if verbosity > 1: print >> console, "Inspecting the available layers in GeoServer ..." url = "%srest" % settings.GEOSERVER_BASE_URL cat = Catalog(url, _user, _password) if workspace is not None: workspace = cat.get_workspace(workspace) resources = cat.get_resources(workspace=workspace) elif store is not None: store = cat.get_store(store) resources = cat.get_resources(store=store) else: resources = cat.get_resources(workspace=workspace) if filter: resources = [k for k in resources if filter in k.name] # filter out layers explicitly disabled by geoserver resources = [k for k in resources if k.enabled == "true"] # TODO: Should we do something with these? # i.e. look for matching layers in GeoNode and also disable? disabled_resources = [k for k in resources if k.enabled == "false"] number = len(resources) if verbosity > 1: msg = "Found %d layers, starting processing" % number print >> console, msg output = [] for i, resource in enumerate(resources): name = resource.name store = resource.store workspace = store.workspace try: # Avoid circular import problem from geonode.layers.models import Layer layer, created = Layer.objects.get_or_create(name=name, defaults = { "workspace": workspace.name, "store": store.name, "storeType": store.resource_type, "typename": "%s:%s" % (workspace.name, resource.name), "title": resource.title or 'No title provided', "abstract": resource.abstract or 'No abstract provided', "owner": owner, "uuid": str(uuid.uuid4()) }) layer.save() except Exception, e: if ignore_errors: status = 'failed' exception_type, error, traceback = sys.exc_info() else: if verbosity > 0: msg = "Stopping process because --ignore-errors was not set and an error was found." print >> sys.stderr, msg raise Exception('Failed to process %s' % resource.name, e), None, sys.exc_info()[2] else: if created: layer.set_default_permissions() status = 'created' else: status = 'updated' msg = "[%s] Layer %s (%d/%d)" % (status, name, i+1, number) info = {'name': name, 'status': status} if status == 'failed': info['traceback'] = traceback info['exception_type'] = exception_type info['error'] = error output.append(info) if verbosity > 0: print >> console, msg
class CatalogTests(unittest.TestCase): def setUp(self): self.cat = Catalog("http://localhost:8080/geoserver/rest") def testAbout(self): about_html = self.cat.about() self.assertTrue('<html xmlns="http://www.w3.org/1999/xhtml"' in about_html) def testGSVersion(self): version = self.cat.gsversion() pat = re.compile('\d\.\d(\.[\dx]|-SNAPSHOT)') self.assertTrue(pat.match('2.2.x')) self.assertTrue(pat.match('2.3.2')) self.assertTrue(pat.match('2.3-SNAPSHOT')) self.assertFalse(pat.match('2.3.y')) self.assertFalse(pat.match('233')) self.assertTrue(pat.match(version)) def testWorkspaces(self): self.assertEqual(7, len(self.cat.get_workspaces())) # marking out test since geoserver default workspace is not consistent # self.assertEqual("cite", self.cat.get_default_workspace().name) self.assertEqual("topp", self.cat.get_workspace("topp").name) def testStores(self): topp = self.cat.get_workspace("topp") sf = self.cat.get_workspace("sf") self.assertEqual(9, len(self.cat.get_stores())) self.assertEqual(2, len(self.cat.get_stores(topp))) self.assertEqual(2, len(self.cat.get_stores(sf))) self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile", topp).name) self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name) self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name) self.assertEqual("sfdem", self.cat.get_store("sfdem", sf).name) self.assertEqual("sfdem", self.cat.get_store("sfdem").name) def testResources(self): topp = self.cat.get_workspace("topp") sf = self.cat.get_workspace("sf") states = self.cat.get_store("states_shapefile", topp) sfdem = self.cat.get_store("sfdem", sf) self.assertEqual(19, len(self.cat.get_resources())) self.assertEqual(1, len(self.cat.get_resources(states))) self.assertEqual(5, len(self.cat.get_resources(workspace=topp))) self.assertEqual(1, len(self.cat.get_resources(sfdem))) self.assertEqual(6, len(self.cat.get_resources(workspace=sf))) self.assertEqual("states", self.cat.get_resource("states", states).name) self.assertEqual("states", self.cat.get_resource("states", workspace=topp).name) self.assertEqual("states", self.cat.get_resource("states").name) states = self.cat.get_resource("states") fields = [ states.title, states.abstract, states.native_bbox, states.latlon_bbox, states.projection, states.projection_policy ] self.assertFalse(None in fields, str(fields)) self.assertFalse(len(states.keywords) == 0) self.assertFalse(len(states.attributes) == 0) self.assertTrue(states.enabled) self.assertEqual("sfdem", self.cat.get_resource("sfdem", sfdem).name) self.assertEqual("sfdem", self.cat.get_resource("sfdem", workspace=sf).name) self.assertEqual("sfdem", self.cat.get_resource("sfdem").name) def testLayers(self): expected = set(["Arc_Sample", "Pk50095", "Img_Sample", "mosaic", "sfdem", "bugsites", "restricted", "streams", "archsites", "roads", "tasmania_roads", "tasmania_water_bodies", "tasmania_state_boundaries", "tasmania_cities", "states", "poly_landmarks", "tiger_roads", "poi", "giant_polygon" ]) actual = set(l.name for l in self.cat.get_layers()) missing = expected - actual extras = actual - expected message = "Actual layer list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing) self.assert_(len(expected ^ actual) == 0, message) states = self.cat.get_layer("states") self.assert_("states", states.name) self.assert_(isinstance(states.resource, ResourceInfo)) self.assertEqual(set(s.name for s in states.styles), set(['pophatch', 'polygon'])) self.assertEqual(states.default_style.name, "population") def testLayerGroups(self): expected = set(["tasmania", "tiger-ny", "spearfish"]) actual = set(l.name for l in self.cat.get_layergroups()) missing = expected - actual extras = actual - expected message = "Actual layergroup list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing) self.assert_(len(expected ^ actual) == 0, message) tas = self.cat.get_layergroup("tasmania") self.assert_("tasmania", tas.name) self.assert_(isinstance(tas, LayerGroup)) self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers) self.assertEqual(tas.styles, [None, None, None, None], tas.styles) def testStyles(self): self.assertEqual(20, len(self.cat.get_styles())) self.assertEqual("population", self.cat.get_style("population").name) self.assertEqual("popshade.sld", self.cat.get_style("population").filename) self.assertEqual("population", self.cat.get_style("population").sld_name) self.assert_(self.cat.get_style('non-existing-style') is None) def testEscaping(self): # GSConfig is inconsistent about using exceptions vs. returning None # when a resource isn't found. # But the basic idea is that none of them should throw HTTP errors from # misconstructed URLS self.cat.get_style("best style ever") self.cat.get_workspace("best workspace ever") try: self.cat.get_store(workspace="best workspace ever", name="best store ever") self.fail('expected exception') except FailedRequestError, fre: self.assertEqual('No store found named: best store ever', fre.message) try: self.cat.get_resource(workspace="best workspace ever", store="best store ever", name="best resource ever") except FailedRequestError, fre: self.assertEqual('No store found named: best store ever', fre.message)