changeset 1702:49b89575ab31

Import configuration: [WIP] Added table for extra configuration attributes.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 07 Jan 2019 13:23:39 +0100
parents f4bd67daaaff
children d0830ebb3a23
files pkg/controllers/importconfig.go pkg/imports/config.go schema/gemma.sql
diffstat 3 files changed, 95 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/pkg/controllers/importconfig.go	Mon Jan 07 12:13:52 2019 +0100
+++ b/pkg/controllers/importconfig.go	Mon Jan 07 13:23:39 2019 +0100
@@ -18,6 +18,7 @@
 	"errors"
 	"fmt"
 	"net/http"
+	"sort"
 	"strconv"
 
 	"github.com/gorilla/mux"
@@ -51,6 +52,11 @@
 VALUES ($1, $2, $3, $4, $5, $6)
 RETURNING id`
 
+	insertImportConfigurationAttributeSQL = `
+INSERT INTO waterway.import_configuration_attributes
+(import_configuration_id, k, v)
+VALUES ($1, $2, $3)`
+
 	hasImportConfigurationSQL = `
 SELECT true FROM waterway.import_configuration
 WHERE id = $1`
@@ -315,6 +321,30 @@
 		return
 	}
 
+	// Store extra attributes
+	if attrs := importConfig.Attributes; len(attrs) > 0 {
+		var attrStmt *sql.Stmt
+		attrStmt, err = tx.PrepareContext(ctx, insertImportConfigurationAttributeSQL)
+		if err != nil {
+			return
+		}
+		defer attrStmt.Close()
+		// Sort to make it deterministic
+		keys := make([]string, 0, len(attrs))
+		for key, value := range importConfig.Attributes {
+			// Ignore nil values.
+			if value != nil {
+				keys = append(keys, key)
+			}
+		}
+		sort.Strings(keys)
+		for _, key := range keys {
+			if _, err = attrStmt.ExecContext(ctx, id, key, *attrs[key]); err != nil {
+				return
+			}
+		}
+	}
+
 	// Need to start a scheduler job right away?
 	if importConfig.Cron != nil {
 		if err = scheduler.BindAction(
--- a/pkg/imports/config.go	Mon Jan 07 12:13:52 2019 +0100
+++ b/pkg/imports/config.go	Mon Jan 07 13:23:39 2019 +0100
@@ -32,6 +32,10 @@
 	// of the registered import types.
 	ImportKind string
 
+	// ConfigAttributes is a map of optional key/value attributes
+	// of an import configuration.
+	ConfigAttributes map[string]*string
+
 	// Config is JSON serialized form of a import configuration.
 	Config struct {
 		// Kind is the import type.
@@ -50,21 +54,37 @@
 		Cron *CronSpec `json:"cron"`
 		// URL is an optional URL used by the import.
 		URL *string `json:"url"`
+		// Attributes are optional key/value pairs for a configuration.
+		Attributes ConfigAttributes `json:"attributes,omitempty"`
 	}
 
 	// IDConfig is the same as Config with an ID.
 	// Mainly used for server delivered configurations.
 	IDConfig struct {
-		ID         int64      `json:"id"`
-		User       string     `json:"user"`
-		Kind       ImportKind `json:"kind"`
-		SendEMail  bool       `json:"send-email"`
-		AutoAccept bool       `json:"auto-accept"`
-		Cron       *CronSpec  `json:"cron,omitempty"`
-		URL        *string    `json:"url,omitempty"`
+		ID         int64            `json:"id"`
+		User       string           `json:"user"`
+		Kind       ImportKind       `json:"kind"`
+		SendEMail  bool             `json:"send-email"`
+		AutoAccept bool             `json:"auto-accept"`
+		Cron       *CronSpec        `json:"cron,omitempty"`
+		URL        *string          `json:"url,omitempty"`
+		Attributes ConfigAttributes `json:"attributes,omitempty"`
 	}
 )
 
+// Get fetches a value for given key out of the configuration.
+// If the key was not found the bool component of the return value
+// return false.
+func (ca ConfigAttributes) Get(key string) (string, bool) {
+	if ca == nil {
+		return "", false
+	}
+	if value, found := ca[key]; found && value != nil {
+		return *value, true
+	}
+	return "", false
+}
+
 // UnmarshalJSON checks if the incoming string
 // is a registered import type.
 func (ik *ImportKind) UnmarshalJSON(data []byte) error {
@@ -110,6 +130,11 @@
   url
 FROM waterway.import_configuration
 WHERE id = $1`
+
+	loadConfigAttributesSQL = `
+SELECT k, v
+FROM waterway.import_configuration_attributes
+WHERE import_configuration_id = $1`
 )
 
 func loadIDConfig(id int64) (*IDConfig, error) {
@@ -138,6 +163,29 @@
 		if url.Valid {
 			cfg.URL = &url.String
 		}
+		// load the extra attributes.
+		rows, err := conn.QueryContext(ctx, loadConfigAttributesSQL, id)
+		if err != nil {
+			return err
+		}
+		defer rows.Close()
+		var attributes map[string]*string
+		for rows.Next() {
+			var k, v string
+			if err = rows.Scan(&k, &v); err != nil {
+				return err
+			}
+			if attributes == nil {
+				attributes = map[string]*string{}
+			}
+			attributes[k] = &v
+		}
+		if err = rows.Err(); err != nil {
+			return err
+		}
+		if len(attributes) > 0 {
+			cfg.Attributes = attributes
+		}
 		return nil
 	})
 
--- a/schema/gemma.sql	Mon Jan 07 12:13:52 2019 +0100
+++ b/schema/gemma.sql	Mon Jan 07 13:23:39 2019 +0100
@@ -563,6 +563,16 @@
         cron varchar,
         url  varchar
     )
+
+    CREATE TABLE import_configuration_attributes (
+        import_configuration_id int NOT NULL
+          REFERENCES import_configuration(id)
+            ON DELETE CASCADE
+            ON UPDATE CASCADE,
+        k VARCHAR NOT NULL,
+        v TEXT NOT NULL,
+        UNIQUE (import_configuration_id, k)
+    )
 ;
 
 -- Configure primary keys for geoserver views