Beispiel #1
0
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)
Beispiel #2
0
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.assertIsNone(self.cat.get_layer('import'))
            self.cat.publish_featuretype("import", ds, native_crs="EPSG:4326")
            # and now it's not
            self.assertIsNotNone(self.cat.get_layer('import'))
        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 Exception:
                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)
        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.assertEqual(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.assertEqual(set(rs.request_srs_list), srs_after,
                         str(rs.request_srs_list))

        # set and save response_srs_list
        self.assertEqual(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.assertEqual(set(rs.response_srs_list), srs_after,
                         str(rs.response_srs_list))

        # set and save supported_formats
        self.assertEqual(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.assertEqual(set(rs.supported_formats), formats_after,
                         str(rs.supported_formats))

    def testWmsStoreCreate(self):
        ws = self.cat.create_wmsstore("wmsstore_gsconfig")
        ws.capabilitiesURL = "http://mesonet.agron.iastate.edu/cgi-bin/wms/iowa/rainfall.cgi?VERSION=1.1.1&REQUEST=GetCapabilities&SERVICE=WMS&"  # noqa: E501
        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://mesonet.agron.iastate.edu/cgi-bin/wms/iowa/rainfall.cgi?VERSION=1.1.1&REQUEST=GetCapabilities&SERVICE=WMS&"  # noqa: E501
        wmsstore.type = "WMS"
        self.cat.save(wmsstore)
        wmsstore = self.cat.get_store("wmsstore")
        self.assertEqual(1, len(self.cat.get_stores(workspace=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(':', '_')
            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.items():
            self.assertEqual(v, shapefile_plus_sidecars[k])

        sf = self.cat.get_workspace("sf")
        self.cat.create_featurestore("states_test", shapefile_plus_sidecars,
                                     sf)

        self.assertIsNotNone(self.cat.get_resource("states_test",
                                                   workspace=sf))

        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.assertIsNone(self.cat.get_layer("states_test"))

    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")
        self.cat.create_coveragestore("Pk50095", tiffdata, sf)

        self.assertIsNotNone(self.cat.get_resource("Pk50095", workspace=sf))

        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))

        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 = next(
            (s for s in lyr.styles if s.name == "pophatch"))
        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
        with open("test/fred.sld") as fred_sld:
            self.cat.create_style("fred", fred_sld.read())
        fred = self.cat.get_style("fred")
        self.assertIsNotNone(fred)
        self.assertEqual("Fred", fred.sld_title)

        # replace style, verify changes
        with open("test/ted.sld") as ted_sld:
            self.cat.create_style("fred", ted_sld.read(), overwrite=True)
        fred = self.cat.get_style("fred")
        self.assertIsNotNone(fred)
        self.assertEqual("Ted", fred.sld_title)

        # delete style, verify non-existence
        self.cat.delete(fred, purge=True)
        self.assertIsNone(self.cat.get_style("fred"))

        # attempt creating new style
        with open("test/fred.sld") as fred_sld:
            self.cat.create_style("fred", 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.assertIsNotNone(f)
        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"
        with open("test/notitle.sld") as notitle_sld:
            self.cat.create_style("notitle", notitle_sld.read())
        notitle = self.cat.get_style("notitle")
        self.assertEqual(None, notitle.sld_title)

    def testWorkspaceStyles(self):
        # upload new style, verify existence
        with open("test/fred.sld") as fred_sld:
            self.cat.create_style("jed", fred_sld.read(), workspace="topp")

        jed = self.cat.get_style("jed", workspace="blarny")
        self.assertIsNone(jed)
        jed = self.cat.get_style("jed", workspace="topp")
        self.assertIsNotNone(jed)
        self.assertEqual("Fred", jed.sld_title)
        jed = self.cat.get_style("topp:jed")
        self.assertIsNotNone(jed)
        self.assertEqual("Fred", jed.sld_title)

        # replace style, verify changes
        with open("test/ted.sld") as ted_sld:
            self.cat.create_style("jed",
                                  ted_sld.read(),
                                  overwrite=True,
                                  workspace="topp")
        jed = self.cat.get_style("jed", workspace="topp")
        self.assertIsNotNone(jed)
        self.assertEqual("Ted", jed.sld_title)

        # delete style, verify non-existence
        self.cat.delete(jed, purge=True)
        self.assertIsNone(self.cat.get_style("jed", workspace="topp"))

        # attempt creating new style
        with open("test/fred.sld") as fred_sld:
            self.cat.create_style("jed", 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.assertIsNotNone(f)
        self.assertEqual(f.fqn, jed.fqn)

    def testLayerWorkspaceStyles(self):
        # upload new style, verify existence
        with open("test/fred.sld") as fred_sld:
            self.cat.create_style("ned",
                                  fred_sld.read(),
                                  overwrite=True,
                                  workspace="topp")
        with open("test/fred.sld") as ted_sld:
            self.cat.create_style("zed",
                                  ted_sld.read(),
                                  overwrite=True,
                                  workspace="topp")
        ned = self.cat.get_style("ned", workspace="topp")
        zed = self.cat.get_style("zed", workspace="topp")
        self.assertIsNotNone(ned)
        self.assertIsNotNone(zed)

        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()
        if lyr.default_style is not None:
            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.assertIsNone(ws)

    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.assertTrue(states.enabled)
        states.enabled = False
        self.assertFalse(states.enabled)
        self.cat.save(states)

        states = self.cat.get_store('states_shapefile')
        self.assertFalse(states.enabled)

        states.enabled = True
        self.cat.save(states)

        states = self.cat.get_store('states_shapefile')
        self.assertTrue(states.enabled)

    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'
        with open('test/data/mosaic/cea.zip', 'rb') as data:
            self.cat.create_imagemosaic(name, data)

        # get the layer resource back
        self.cat._cache.clear()
        resource = self.cat.get_layer(name).resource

        self.assertIsNotNone(resource)

        # delete granule from mosaic
        coverage = name
        store = self.cat.get_store(name)
        granules = self.cat.list_granules(coverage, store)
        self.assertEqual(1, len(granules['features']))
        granule_id = name + '.1'
        self.cat.mosaic_delete_granule(coverage, store, granule_id)
        granules = self.cat.list_granules(coverage, store)
        self.assertEqual(0, len(granules['features']))
        """
          testing external Image mosaic creation
        """
        name = 'cea_mosaic_external'
        path = 'test/data/mosaic/external'
        self.cat.create_imagemosaic(name, path, workspace='topp')
        self.cat._cache.clear()
        resource = self.cat.get_layer("external").resource
        self.assertIsNotNone(resource)

        # add granule to mosaic
        granule_path = 'test/data/mosaic/granules/cea_20150102.tif'
        self.cat.add_granule(granule_path, name, workspace='topp')
        granules = self.cat.list_granules("external", name, 'topp')
        self.assertEqual(2, len(granules['features']))

        # add external granule to mosaic
        granule_path = os.path.join(
            os.getcwd(), 'test/data/mosaic/granules/cea_20150103.zip')
        self.cat.add_granule(granule_path, name, workspace='topp')
        granules = self.cat.list_granules("external", name, 'topp')
        self.assertEqual(3, len(granules['features']))

        # Delete store
        store = self.cat.get_store(name)
        self.cat.delete(store, purge=True, recurse=True)
        self.cat._cache.clear()

    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  # noqa: E501

        # 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)
Beispiel #3
0
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)
Beispiel #4
0
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 GeoServer(Server):
    """
    Represents a server running GeoServer [1], an application that provides access to layers.

    This class provides a concrete implementation of the more generic Server component (which is intentionally generic).
    Currently the Server class does not dictate an interface for accessing resources but this class aims to present
    GeoServer specific components (such as workspaces) as generic components (such as namespaces).

    GeoServer instances typically represent individual instances (i.e. hosts are servers) rather than a wider and more
    abstract platform offered by a service provider.

    Information on layers and other resources are fetched using a combination of the GeoServer specific administrative
    API [2] accessed through geoserver-restconfig [3] and OGC services accessed through OWSLib [4] (and currently
    limited to WMS and WFS).

    [1] https://geoserver.readthedocs.io/en/latest/
    [2] https://geoserver.readthedocs.io/en/latest/rest/index.html
    [3] https://pypi.org/project/geoserver-restconfig
    [4] https://pypi.org/project/OWSLib/
    """
    def __init__(
        self,
        server_id: str,
        label: str,
        hostname: str,
        port: str,
        api_path: str,
        wms_path: str,
        wfs_path: str,
        username: str,
        password: str,
    ):
        """
        :param server_id: unique identifier, typically a ULID (Universally Unique Lexicographically Sortable Identifier)
        :param label: a human readable, well-known, identifier for the server - typically based on the hostname
        :param hostname: servers fully qualified hostname
        :param port: port on which GeoServer is running (usually '80' or '8080')
        :param api_path: URL path, relative to the root of the server, to the GeoServer API (usually '/geoserver/rest')
        :param wms_path: URL path, relative to the root of the server, to the GeoServer WMS endpoint (usually
        '/geoserver/ows?service=wms&version=1.3.0&request=GetCapabilities')
        :param wfs_path: URL path, relative to the root of the server, to the GeoServer WFS endpoint (usually
        '/geoserver/ows?service=wfs&version=2.0.0&request=GetCapabilities')
        :param username: username for account to use for GeoServer API
        :param password: password for account to use for GeoServer API
        """
        endpoint = build_base_data_source_endpoint(data_source={
            "hostname": hostname,
            "port": port
        })

        self.client = Catalogue(service_url=f"{endpoint}{api_path}",
                                username=username,
                                password=password)
        self.wms = WebMapService(url=f"{endpoint}{wms_path}",
                                 version="1.3.0",
                                 username=username,
                                 password=password)
        self.wfs = WebFeatureService(url=f"{endpoint}{wfs_path}",
                                     version="2.0.0",
                                     username=username,
                                     password=password)

        super().__init__(
            server_id=server_id,
            label=label,
            hostname=hostname,
            server_type=ServerType.GEOSERVER.value,
            version=self._get_geoserver_version(),
        )

    def get_namespaces(self) -> List[str]:
        """
        Gets all GeoServer workspace names as Namespace labels

        :return: list of Namespace labels
        """
        workspaces = []
        for workspace in self.client.get_workspaces():
            workspaces.append(workspace.name)
        return workspaces

    def get_namespace(self, namespace_reference: str) -> Dict[str, str]:
        """
        Gets a specific workspace as a Namespace

        Note: GeoServer workspaces do not support the concept of a title, a static substitute value is therefore used
        Note: GeoServer workspaces do support the concept of a namespace, but it is not yet implemented [#28]

        :param namespace_reference: Namespace (workspace) label (name)

        :return: dictionary of Namespace information that can be made into a Namespace object
        """
        workspace = self.client.get_workspace(name=namespace_reference)
        if workspace is None:
            raise KeyError(
                f"Namespace [{namespace_reference}] not found in server [{self.label}]"
            )

        return {"label": workspace.name, "title": "-", "namespace": "-"}

    def get_repositories(self) -> List[Tuple[str, str]]:
        """
        Gets all GeoServer store names as Repository labels

        :return: list of Repository:Namespace label tuples
        """
        stores = []
        # Passing workspaces here is a workaround for a bug in the get stores method where workspaces aren't specified.
        # The method says all workspaces should be checked but the logic to do this is in the wrong place so none are.
        for store in self.client.get_stores(
                workspaces=self.client.get_workspaces()):
            stores.append((store.name, store.workspace.name))
        return stores

    def get_repository(self, repository_reference: str,
                       namespace_reference: str) -> Dict[str, str]:
        """
        Gets a specific store as a Repository

        If a Namespace (workspace) label is specified the Repository must exist within that Namespace.

        GeoServer store types are sometimes unsuitable or non-standard and so need to be mapped to a conventional value.
        in the RepositoryType enum using the GeoServerRepositoryType enum.

        Note: GeoServer stores do not support the concept of a title, a static substitute value is therefore used
        Note: Names (labels) will be returned for related components instead of identifiers or complete objects [#33]

        :param repository_reference: Repository (store) label (name)
        :param namespace_reference: Namespace (store) label (name)
        :return: dictionary of repository information that can be made into a Repository object
        """
        _store = self.client.get_store(name=repository_reference,
                                       workspace=namespace_reference)
        if _store is None:
            raise KeyError(
                f"Repository [{repository_reference}] not found in server [{self.label}]"
            )

        store = {
            "label":
            _store.name,
            "title":
            "-",
            "repository_type":
            RepositoryType[GeoServerRepositoryType(str(
                _store.type).lower()).name].value,
            "namespace_label":
            _store.workspace.name,
        }
        if hasattr(_store, "description") and _store.description is not None:
            store["title"] = _store.description

        if (store["repository_type"] == RepositoryType.POSTGIS.value
                or store["repository_type"] == RepositoryType.ORACLE.value):
            store["hostname"] = _store.connection_parameters["host"]
            store["database"] = _store.connection_parameters["database"]
            store["schema"] = _store.connection_parameters["schema"]
        return store

    def get_styles(self) -> List[Tuple[str, Optional[str]]]:
        """
        Gets all GeoServer style names as Style labels

        Python's None value will be used to represent the Namespace of global styles (i.e that don't have a Namespace
        (workspace)).

        :return: list of Style:Namespace label tuples
        """
        styles = []

        for _style in self.client.get_styles():
            styles.append((_style.name, _style.workspace))

        return styles

    def get_style(self,
                  style_reference: str,
                  namespace_reference: str = None) -> Dict[str, str]:
        """
        Gets a specific style as a Style

        If a Namespace (workspace) label is specified the Style must exist within that Namespace.

        Note: GeoServer styles do support the concept of a title, but it is not exposed through the admin API so a
        static substitute value is therefore used
        Note: Names (labels) will be returned for related components instead of identifiers or complete objects [#33]

        :param style_reference: Style (style) label (name)
        :param namespace_reference: Namespace (store) label (name)
        :return: dictionary of style information that can be made into a Style object
        """
        _style = self.client.get_style(name=style_reference,
                                       workspace=namespace_reference)

        _type = str(_style.style_format).lower()
        if _type == "sld10":
            _type = "sld"

        style = {
            "label": _style.name,
            "title": "-",
            "style_type": _type,
        }
        if hasattr(_style, "workspace") and _style.workspace is not None:
            style["namespace_label"] = _style.workspace

        return style

    def get_layers(self) -> List[str]:
        """
        Gets all GeoServer layer names as Layer labels

        :return: list of Layer labels
        """
        layers = []

        for _layer in self.client.get_layers():
            layers.append(_layer.name)

        return layers

    def get_layer(
        self, layer_reference: str
    ) -> Dict[str, Union[Optional[str], List[str], List[Tuple[
            str, Optional[str]]]]]:
        """
        Gets a specific layer as a Layer

        Note: Names (labels) will be returned for related components instead of identifiers or complete objects [#33]

        :param layer_reference: Layer (layer) label (name)
        :return: dictionary of layer information that can be made into a Layer object
        """
        _layer = self.client.get_layer(name=layer_reference)

        layer = {
            "label":
            _layer.resource.name,
            "title":
            _layer.resource.title,
            "layer_type":
            str(_layer.type).lower(),
            "geometry_type":
            None,
            "services": [],
            "table_view":
            None,
            "namespace_label":
            _layer.resource.workspace.name,
            "repository_label":
            _layer.resource.store.name,
            "style_labels":
            [(_layer.default_style.name, _layer.default_style.workspace)],
        }

        if layer_reference in list(
                self.wms.contents
        ) or f"{_layer.resource.workspace.name}:{layer_reference}" in list(
                self.wms.contents):
            layer["services"].append(LayerService.WMS.value)

        if layer_reference in list(
                self.wfs.contents
        ) or f"{_layer.resource.workspace.name}:{layer_reference}" in list(
                self.wfs.contents):
            layer["services"].append(LayerService.WFS.value)

            # WFS lookups don't seem to mind if the layer is namespaced or not
            _properties = self.wfs.get_schema(layer_reference)
            if "geometry" in _properties and isinstance(
                    _properties["geometry"], str):
                try:
                    layer["geometry_type"] = LayerGeometry[
                        GeoServerLayerGeometry(str(
                            _properties["geometry"])).name].value
                except ValueError:
                    raise ValueError(
                        f"Geometry [{_properties['geometry']}] for layer {layer_reference} not mapped to "
                        f"LayerGeometry enum.")
            elif "properties" in _properties:
                for geometry_column_name in GeoServerGeometryColumnNames:
                    if geometry_column_name.value in _properties[
                            "properties"].keys():
                        try:
                            layer["geometry_type"] = LayerGeometry[
                                GeoPropertyGeoServerLayerGeom(
                                    str(_properties["properties"][
                                        geometry_column_name.value])
                                ).name].value
                        except ValueError:
                            raise ValueError(
                                f"Geometry [{_properties['properties'][geometry_column_name.value]}] for layer "
                                f"{layer_reference} in column '{geometry_column_name.value}' not mapped to "
                                f"LayerGeometry enum.")

        if (str(_layer.resource.store.type).lower()
                == RepositoryType.POSTGIS.value
                or str(_layer.resource.store.type).lower()
                == RepositoryType.ORACLE.value):
            layer["table_view"] = _layer.resource.native_name

        return layer

    def get_layer_groups(self) -> List[Tuple[str, Optional[str]]]:
        """
        Gets all GeoServer layer group names as LayerGroup labels

        Python's None value will be used to represent the Namespace of global layer groups (i.e that don't have a
        Namespace (workspace)).

        :return: list of LayerGroup:Namespace label tuples
        """
        layer_groups = []

        for _layer_group in self.client.get_layergroups(
                workspaces=self.client.get_workspaces()):
            layer_groups.append((_layer_group.name, _layer_group.workspace))

        return layer_groups

    def get_layer_group(
        self, layer_group_reference: str, namespace_reference: str
    ) -> Dict[str, Union[Optional[str], List[str], List[Tuple[
            str, Optional[str]]]]]:
        """
        Gets a specific layer group as a LayerGroup

        If a Namespace (workspace) label is specified the LayerGroup must exist within that Namespace.

        Note: Names (labels) will be returned for related components instead of identifiers or complete objects [#33]

        :param layer_group_reference: LayerGroup (layer group) label (name)
        :param namespace_reference: Namespace (store) label (name)
        :return: dictionary of layer group information that can be made into a LayerGroup object
        """
        _layer_group = self.client.get_layergroup(
            name=layer_group_reference, workspace=namespace_reference)

        layer_group = {
            "label": _layer_group.name,
            "title": _layer_group.title,
            "services": [],
            "namespace_label": _layer_group.workspace,
            "layer_labels": [],
            "style_labels": [],
        }
        for layer_label in _layer_group.layers:
            layer_label = layer_label.split(":")
            if len(layer_label) == 2:
                layer_group["layer_labels"].append(
                    (layer_label[1], layer_label[0]))
            elif len(layer_label) == 1:
                layer_group["layer_labels"].append((layer_label[0], None))

        if f"{namespace_reference}:{layer_group_reference}" in list(
                self.wms.contents):
            layer_group["services"].append(LayerService.WMS.value)
        if f"{namespace_reference}:{layer_group_reference}" in list(
                self.wfs.contents):
            layer_group["services"].append(LayerService.WFS.value)
            _properties = self.wfs.get_schema(
                f"{namespace_reference}:{layer_group_reference}")
            try:
                layer_group["geometry_type"] = LayerGeometry[
                    GeoServerLayerGeometry(str(
                        _properties["geometry"])).name].value
            except ValueError:
                raise ValueError(
                    f"Geometry [{_properties['geometry']}] not mapped to LayerGeometry enum."
                )

        for style_label in _layer_group.styles:
            if style_label is not None:
                style_label = style_label.split(":")
                if len(style_label) == 2 and (
                        style_label[1],
                        style_label[0]) not in layer_group["style_labels"]:
                    layer_group["style_labels"].append(
                        (style_label[1], style_label[0]))
                if len(style_label) == 1 and (
                        style_label[0],
                        None) not in layer_group["style_labels"]:
                    layer_group["style_labels"].append((style_label[0], None))

        return layer_group

    def _get_geoserver_version(self) -> str:
        """
        Gets the GeoServer version

        :return: GeoServer version string
        """
        return self.client.get_version()
Beispiel #6
0
class wrap_geoserver:
    """ Geoserver (gsconfig) wrapper """
    def __init__(self,
                 geoserver_name,
                 username=username,
                 password=password,
                 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
Beispiel #7
0
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)
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
Beispiel #9
0
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 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")
Beispiel #11
0
# 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')
output.write(netcdfFile, projectName + '.nc', zipfile.ZIP_DEFLATED)
output.close()

# upload zip file (creating coveragestore and layers automatically)
logging.info('Uploading ' + zfile)
with open(output.filename, 'rb') as zip_file:
    r_create_layer = session.put(geoserver_url + '/workspaces/' + workspace + '/coveragestores/' + projectName + '/file.netcdf',
                                 data=zip_file,
class GeoserverLayers(object):

    def __init__(self, gs_apirest, username, password):
        try:
            self.__catalog = Catalog(gs_apirest, username=username, password=password)

        except Exception as err:
            print("Geoserver API Rest Error: {0}".format(err))

    def __createSldStyle(self, sldpath, stylename, ovwrt=False):
        try:
            styles_list = [st.name for st in self.__catalog.get_styles()]
            if ovwrt or not stylename in styles_list:
                with open(sldpath) as f:
                    self.__catalog.create_style(stylename, f.read(), overwrite=ovwrt)
            else:
                print("This style already exists...")

        except Exception as err:
            print("Geoserver API Rest Error creating new style: {0}".format(err))

    def __rmvResources(self, rsrc):
        """
        Removing resources
        """
        self.__catalog.delete(rsrc)
        self.__catalog.reload()

    def rmvStyle(self, stylename):
        """
        Remove style
        """
        try:

            style = self.__catalog.get_style(stylename)
            self.__rmvResources(style)

        except Exception as err:
            print("Geoserver API Rest Error removing style: {0}".format(err))

    def rmvDataStore(self, ds_store):
        """
        Remove DataStore (with his layer)
        """
        try:

            lay_rm = self.__catalog.get_layer(ds_store)
            self.__rmvResources(lay_rm)

            str_rm = self.__catalog.get_store(ds_store)
            self.__rmvResources(str_rm)

        except Exception as err:
            print("Geoserver API Rest Error removing data store: {0}".format(err))

    def createGeoserverWMSLayer(self, data, ws_name, ds_name, stylename, sldpath, debug=False):
        """
        Create Geoserver WMS layer

        Status codes:
             2 : "Geoserver layer successfully created"
            -1 : "Workspace does not exist"
            -2 : "Datastore already exists"
            -3 : "Error creating Geoserver layer"
            -4 : "File missing"
        """
        try:

            if not self.__catalog.get_workspace(ws_name):
                print("Workspace does not exist")
                return -1

            ds_list = [i.name for i in self.__catalog.get_stores()]
            if ds_name in ds_list:
                print("Datastore already exists")
                return -2

            ds = self.__catalog.create_datastore(ds_name, ws_name)
            ft = self.__catalog.create_featurestore(ds_name, workspace=ws_name,data=data)

            print("Geoserver layer successfully created...")

            self.__createSldStyle(sldpath, stylename)
            lyr = self.__catalog.get_layer(ds_name)
            lyr.enabled = True
            lyr.default_style = stylename
            self.__catalog.save(lyr)

            if debug:
                rsrc = self.__catalog.get_resource(ds_name, workspace=ws_name)
                print("Data Store XML: {}".format(rsrc.href))

            return 2

        except Exception as err:
            print("Geoserver API Rest Error creating new layer: {0}".format(err))
            return -3
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
Beispiel #14
0
gspwd=os.environ['GS_ADMIN_PASS']

cat = Catalog("http://localhost:8080/geoserver/rest", "admin", gspwd)
layers=cat.get_layers()

print "............. All  layers ........ "
for eachl in layers:
    print eachl.name


print ".............. Workspaces ........ "

worksp=cat.get_workspaces()

for wk in worksp:
    print wk.name

print ".............. Stores ........ "

stores=cat.get_stores()

for st in stores:
    print st.name

print ".............. Styles ........ "

styles=cat.get_styles()

for st in styles:
    print st.name