Mercurial > gemma
view cmd/gemma/geoserver.go @ 414:c1047fd04a3a
Moved project specific Go packages to new pkg folder.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Wed, 15 Aug 2018 17:30:50 +0200 |
parents | 0b8921797064 |
children | ff26ffc18a04 |
line wrap: on
line source
package main import ( "bytes" "encoding/json" "fmt" "log" "net/http" "gemma.intevation.de/gemma/pkg/config" "gemma.intevation.de/gemma/pkg/misc" ) const ( workspaceName = "gemma" datastoreName = "gemma" databaseScheme = "waterway" databaseType = "postgis" ) 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) } } func asJSON(req *http.Request) { req.Header.Set("Content-Type", "application/json") } func ensureWorkspace() error { var ( url = config.GeoServerURL() user = config.GeoServerUser() password = config.GeoServerPassword() auth = basicAuth(user, password) ) // Probe workspace. req, err := http.NewRequest( http.MethodGet, url+"/rest/workspaces/"+workspaceName+".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: workspace " + workspaceName + " already exists.") return nil } // Create workspace log.Println("info: creating workspace " + workspaceName) const createJSON = `{"workspace":{"name":"` + workspaceName + `"}}` req, err = http.NewRequest( http.MethodPost, url+"/rest/workspaces", bytes.NewReader([]byte(createJSON))) if err != nil { return err } auth(req) asJSON(req) if resp, err = http.DefaultClient.Do(req); err != nil { return err } if resp.StatusCode != http.StatusCreated { err = fmt.Errorf("Status code '%s' (%d)", http.StatusText(resp.StatusCode), resp.StatusCode) } return err } func ensureDataStore() error { var ( url = config.GeoServerURL() user = config.GeoServerUser() password = config.GeoServerPassword() auth = basicAuth(user, password) ) // Probe datastore. req, err := http.NewRequest( http.MethodGet, url+"/rest/workspaces/"+workspaceName+"/datastores/"+datastoreName+".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: datastore " + datastoreName + " already exists.") return nil } // Create datastore. log.Println("info: creating datastore " + datastoreName) type entry struct { Key interface{} `json:"@key"` Value interface{} `json:"$"` } // Create datastore. ds := map[string]interface{}{ "dataStore": map[string]interface{}{ "name": datastoreName, "connectionParameters": map[string]interface{}{ "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}, }, }, }, } var out bytes.Buffer enc := json.NewEncoder(&out) if err := enc.Encode(&ds); err != nil { return err } req, err = http.NewRequest( http.MethodPost, url+"/rest/workspaces/"+workspaceName+"/datastores", 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 { err = fmt.Errorf("Status code '%s' (%d)", http.StatusText(resp.StatusCode), resp.StatusCode) } return err } func ensureFeatures() error { var ( url = config.GeoServerURL() user = config.GeoServerUser() password = config.GeoServerPassword() auth = basicAuth(user, password) tables = config.GeoServerTables() ) if len(tables) == 0 { log.Println("info: no tables to publish") return nil } log.Printf("info: number of tables to publish %d\n", len(tables)) var features struct { FeatureTypes struct { FeatureType []struct { Name string `json:"name"` } `json:"featureType"` } `json:"featureTypes"` } hasFeature := func(name string) bool { for _, ft := range features.FeatureTypes.FeatureType { if ft.Name == name { return true } } return false } // Fetch all featuretypes. req, err := http.NewRequest( http.MethodGet, url+"/rest/workspaces/"+workspaceName+ "/datastores/"+datastoreName+ "/featuretypes.json", nil) if err != nil { return err } auth(req) resp, err := http.DefaultClient.Do(req) if err != nil { return err } err = json.NewDecoder(resp.Body).Decode(&features) resp.Body.Close() if err != nil { // XXX: Quirk in the JSON return by GeoServer: // If there are no features in the datastore // featureType deserializes to an empty string "" // instead of an empty array *palmface*. // So assume there no features. hasFeature = func(string) bool { return false } } for _, table := range tables { if hasFeature(table) { log.Printf("info: featuretype %s already exists.\n", table) 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 { if config.GeoServerURL() == "" { log.Println("info: No tables to publish on GeoServer") return nil } if err := ensureWorkspace(); err != nil { return err } if err := ensureDataStore(); err != nil { return err } // TODO: Styles return ensureFeatures() }