changeset 395:272ed64a5053

Create feature layers in GeoServer via REST API.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 13 Aug 2018 18:55:43 +0200
parents f24ed1d570c7
children c6290776c65c
files cmd/gemma/geoserver.go
diffstat 1 files changed, 95 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/cmd/gemma/geoserver.go	Mon Aug 13 17:38:24 2018 +0200
+++ b/cmd/gemma/geoserver.go	Mon Aug 13 18:55:43 2018 +0200
@@ -18,12 +18,15 @@
 	databaseType   = "postgis"
 )
 
-const startupSQL = `SET SESSION AUTHORIZATION waterway_user;`
+const (
+	startupSQL = `` // `SET SESSION AUTHORIZATION waterway_user`
+	closeupSQL = `` // `RESET SESSION AUTHORIZATION`
+)
 
 func basicAuth(user, password string) func(req *http.Request) {
 	auth := "Basic " + misc.BasicAuth(user, password)
 	return func(req *http.Request) {
-		req.Header.Add("Authorization", auth)
+		req.Header.Add("authorization", auth)
 	}
 }
 
@@ -59,6 +62,9 @@
 	}
 
 	// Create workspace
+
+	log.Println("info: creating workspace " + workspaceName)
+
 	const createJSON = `{"workspace":{"name":"` + workspaceName + `"}}`
 
 	req, err = http.NewRequest(
@@ -91,7 +97,7 @@
 		auth     = basicAuth(user, password)
 	)
 
-	// Probe  workspace.
+	// Probe datastore.
 	req, err := http.NewRequest(
 		http.MethodGet,
 		url+"/rest/workspaces/"+workspaceName+"/datastores/"+datastoreName+".json",
@@ -110,6 +116,9 @@
 		return nil
 	}
 
+	// Create datastore.
+	log.Println("info: creating datastore " + datastoreName)
+
 	type entry struct {
 		Key   interface{} `json:"@key"`
 		Value interface{} `json:"$"`
@@ -123,11 +132,13 @@
 				"entry": []entry{
 					{"host", config.DBHost()},
 					{"port", config.DBPort()},
+					{"database", config.DBName()},
 					{"schema", databaseScheme},
 					{"user", config.SysAdmin()},
 					{"passwd", config.SysAdminPassword()},
 					{"dbtype", databaseType},
 					{"Session startup SQL", startupSQL},
+					{"Session close-up SQL", closeupSQL},
 				},
 			},
 		},
@@ -161,15 +172,87 @@
 	return err
 }
 
+func ensureFeatures() error {
+	var (
+		url      = config.GeoServerURL()
+		user     = config.GeoServerUser()
+		password = config.GeoServerPassword()
+		auth     = basicAuth(user, password)
+		tables   = config.GeoServerTables()
+	)
+
+	log.Printf("info: number of tables to publish %d\n", len(tables))
+
+	for _, table := range tables {
+		log.Printf("checking layer %s\n", table)
+		// Probe  featuretype.
+		req, err := http.NewRequest(
+			http.MethodGet,
+			url+"/rest/workspaces/"+workspaceName+
+				"/datastores/"+datastoreName+
+				"/featuretypes/"+table+".json",
+			nil)
+		if err != nil {
+			return err
+		}
+		auth(req)
+		resp, err := http.DefaultClient.Do(req)
+		if err != nil {
+			return err
+		}
+
+		if resp.StatusCode != http.StatusNotFound {
+			log.Println("info: featuretype " + table + " already exists.")
+			continue
+		}
+
+		// Create featuretype.
+		log.Printf("info: creating featuretype %s\n", table)
+
+		// Create featuretype
+		ft := map[string]interface{}{
+			"featureType": map[string]interface{}{
+				"name":       table,
+				"nativeName": table,
+				"title":      table,
+			},
+		}
+
+		var out bytes.Buffer
+		enc := json.NewEncoder(&out)
+		if err := enc.Encode(&ft); err != nil {
+			return err
+		}
+
+		req, err = http.NewRequest(
+			http.MethodPost,
+			url+"/rest/workspaces/"+workspaceName+
+				"/datastores/"+datastoreName+
+				"/featuretypes",
+			bytes.NewReader(out.Bytes()))
+		if err != nil {
+			return err
+		}
+		auth(req)
+		asJSON(req)
+		resp, err = http.DefaultClient.Do(req)
+		if err != nil {
+			return err
+		}
+
+		if resp.StatusCode != http.StatusCreated {
+			return fmt.Errorf("Status code '%s' (%d)",
+				http.StatusText(resp.StatusCode),
+				resp.StatusCode)
+		}
+	}
+
+	return nil
+}
+
 func prepareGeoServer() error {
 
-	var (
-		url = config.GeoServerURL()
-		//tables   = config.GeoServerTables()
-	)
-
-	//if url == "" || len(tables) == 0 {
-	if url == "" {
+	if config.GeoServerURL() == "" {
 		log.Println("info: No tables to publish on GeoServer")
 		return nil
 	}
@@ -182,7 +265,7 @@
 		return err
 	}
 
-	// TODO: Create layers.
+	// TODO: Styles
 
-	return nil
+	return ensureFeatures()
 }