geoserver_migrations 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Rakefile +31 -0
- data/app/models/geoserver_migration.rb +21 -0
- data/db/migrate/20180104170500_create_geoserver_migrations.rb +8 -0
- data/lib/generators/geoserver_migrations/add/add_generator.rb +26 -0
- data/lib/generators/geoserver_migrations/add/templates/migration_template.rb +0 -0
- data/lib/generators/geoserver_migrations/install/install_generator.rb +20 -0
- data/lib/generators/geoserver_migrations/install/templates/geoserver_migrations_config.yml +15 -0
- data/lib/generators/geoserver_migrations/migrate/migrate_generator.rb +15 -0
- data/lib/generators/geoserver_migrations/redo/redo_generator.rb +20 -0
- data/lib/generators/geoserver_migrations/rollback/rollback_generator.rb +14 -0
- data/lib/generators/geoserver_migrations/status/status_generator.rb +53 -0
- data/lib/geoserver_migrations.rb +89 -0
- data/lib/geoserver_migrations/api_connector.rb +110 -0
- data/lib/geoserver_migrations/base.rb +13 -0
- data/lib/geoserver_migrations/layer_config.rb +47 -0
- data/lib/geoserver_migrations/layergroup_config.rb +48 -0
- data/lib/geoserver_migrations/migration.rb +116 -0
- data/lib/geoserver_migrations/migration_proxy.rb +34 -0
- data/lib/geoserver_migrations/migrator.rb +109 -0
- data/lib/geoserver_migrations/sld_helpers.rb +338 -0
- data/lib/geoserver_migrations/test_connector.rb +15 -0
- data/lib/geoserver_migrations/version.rb +3 -0
- data/lib/tasks/geoserver_migrations_tasks.rake +4 -0
- metadata +138 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 92b8423112ac07d6f582f135ff9dddc19ad21735
|
4
|
+
data.tar.gz: 9de2a13435f58793d77d197dc64995032bbb5570
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b3a41c386c5f07fa7472b8c3eb1d2be7c89e6872fbba86f0d6f1efc71e5bdd5a121570a0304e30be3baa1788b69d70c130066b01953de3582a5df38be0ac9868
|
7
|
+
data.tar.gz: d2c96d02f7eacca6fc46925c852abb6755a89050675f0df11c9fa7e98906d1c9d0bccf416b799206c0f7cc6a7892a3ae5a287b47dab7db9f2873593d661cd01d
|
data/Rakefile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'GeoserverMigrations'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
require 'rake-version'
|
19
|
+
RakeVersion::Tasks.new do |v|
|
20
|
+
v.copy 'lib/geoserver_migrations/version.rb'
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
Bundler::GemHelper.install_tasks
|
25
|
+
|
26
|
+
require 'rspec/core'
|
27
|
+
require 'rspec/core/rake_task'
|
28
|
+
|
29
|
+
RSpec::Core::RakeTask.new(:spec)
|
30
|
+
|
31
|
+
task default: :spec
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class GeoserverMigration < ActiveRecord::Base
|
2
|
+
|
3
|
+
self.primary_key = 'version'
|
4
|
+
|
5
|
+
def self.all_versions
|
6
|
+
order(:version).pluck(:version)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.set_migrated(migration)
|
10
|
+
self.create!(version: migration.version.to_s)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.set_reverted(migration)
|
14
|
+
self.where(version: migration.version.to_s).destroy_all
|
15
|
+
end
|
16
|
+
|
17
|
+
def version
|
18
|
+
super.to_i
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module GeoserverMigrations
|
2
|
+
module Generators
|
3
|
+
class AddGenerator < ::Rails::Generators::NamedBase
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
5
|
+
|
6
|
+
desc "Adds an empty named migration"
|
7
|
+
|
8
|
+
def add_migration
|
9
|
+
migration_name = file_name.underscore
|
10
|
+
class_name = file_name.camelize
|
11
|
+
|
12
|
+
create_file File.join(Rails.root, GeoserverMigrations.migrations_rootpath, "#{Time.now.strftime('%Y%m%d%H%M%S')}_#{migration_name}.rb"), <<-MIGRATION_FILE
|
13
|
+
class #{class_name} < GeoserverMigrations::Migration
|
14
|
+
|
15
|
+
def run
|
16
|
+
# add migration code here
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
MIGRATION_FILE
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
File without changes
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module GeoserverMigrations
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < ::Rails::Generators::Base
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
5
|
+
desc "This generator installs the default config file, and glue code into application-controller; which you can edit"
|
6
|
+
|
7
|
+
|
8
|
+
def copy_config_file
|
9
|
+
copy_file "geoserver_migrations_config.yml", "config/geoserver_migrations_config.yml"
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_migrations_folder
|
13
|
+
# empty_directory "geoserver", "migrate"
|
14
|
+
empty_directory "geoserver/migrate"
|
15
|
+
empty_directory "geoserver/migrate/assets"
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
development: &common
|
2
|
+
# define migrations_path if you want to keep your migrations in a different folder
|
3
|
+
# migrations_path: 'geoserver/migrate'
|
4
|
+
geoserver_base: "http://localhost:8080/geoserver"
|
5
|
+
api:
|
6
|
+
user: admin
|
7
|
+
password: geoserver
|
8
|
+
workspace: your-workspace
|
9
|
+
datastore: your-datastore
|
10
|
+
|
11
|
+
test:
|
12
|
+
<<: *common # merges key:value pairs defined in development anchor
|
13
|
+
|
14
|
+
production:
|
15
|
+
<<: *common # merges key:value pairs defined in development anchor
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module GeoserverMigrations
|
2
|
+
module Generators
|
3
|
+
class MigrateGenerator < ::Rails::Generators::Base
|
4
|
+
desc "Check and run the needed geoserver migrations"
|
5
|
+
|
6
|
+
def run_migrations
|
7
|
+
migrator = GeoserverMigrations::Migrator.new
|
8
|
+
migrator.migrations_paths = GeoserverMigrations.migrations_rootpath
|
9
|
+
migrator.migrations_paths = GeoserverMigrations.migrations_rootpath
|
10
|
+
migrator.migrate
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module GeoserverMigrations
|
2
|
+
module Generators
|
3
|
+
class RedoGenerator < ::Rails::Generators::Base
|
4
|
+
desc "Redo the last geoserver migrations"
|
5
|
+
|
6
|
+
def rollback_migrations
|
7
|
+
migrator = GeoserverMigrations::Migrator.new
|
8
|
+
migrator.migrations_paths = GeoserverMigrations.migrations_rootpath
|
9
|
+
# there should not be any pending migrations!
|
10
|
+
if migrator.needs_migration?
|
11
|
+
puts "There are pending migrations! We can only redo the last migration if there are no pending migrations."
|
12
|
+
else
|
13
|
+
migrator.rollback
|
14
|
+
migrator.migrate
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module GeoserverMigrations
|
2
|
+
module Generators
|
3
|
+
class RollbackGenerator < ::Rails::Generators::Base
|
4
|
+
desc "Rollback the last geoserver migrations"
|
5
|
+
|
6
|
+
def rollback_migrations
|
7
|
+
migrator = GeoserverMigrations::Migrator.new
|
8
|
+
migrator.migrations_paths = GeoserverMigrations.migrations_rootpath
|
9
|
+
migrator.rollback
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module GeoserverMigrations
|
2
|
+
module Generators
|
3
|
+
class StatusGenerator < ::Rails::Generators::Base
|
4
|
+
desc "Verify geoserver-migrations is setup correctly"
|
5
|
+
|
6
|
+
def check_status
|
7
|
+
puts "Checking configuration ... "
|
8
|
+
errors = []
|
9
|
+
errors << "geoserver_base is not set" unless GeoserverMigrations.config[:geoserver_base].present?
|
10
|
+
errors << "api-user is not set" unless GeoserverMigrations.config[:api][:user].present?
|
11
|
+
errors << "api-password is not set" unless GeoserverMigrations.config[:api][:password].present?
|
12
|
+
|
13
|
+
errors << "Geoserver workspace is not set" unless GeoserverMigrations.config[:workspace].present?
|
14
|
+
errors << "Geoserver datastore is not set" unless GeoserverMigrations.config[:datastore].present?
|
15
|
+
|
16
|
+
unless errors.count > 0
|
17
|
+
puts " --> Configuration ok"
|
18
|
+
else
|
19
|
+
puts "Problems with the configuration-file:\n #{errors.join("\n")}"
|
20
|
+
puts "Check the documentation how to fix them"
|
21
|
+
puts "Did you forget to edit the default config-file or to run rails g geoserver_migrations:install ?"
|
22
|
+
end
|
23
|
+
|
24
|
+
puts "Checking API reachability"
|
25
|
+
begin
|
26
|
+
layers = GeoserverMigrations::Base.connection.test
|
27
|
+
puts " --> Connected to API correctly and retrieved #{layers.count} layers"
|
28
|
+
rescue => e
|
29
|
+
puts " FAILED to reach Geoserver REST API."
|
30
|
+
puts " Error: #{e.message}"
|
31
|
+
end
|
32
|
+
|
33
|
+
puts "Checking database setup"
|
34
|
+
begin
|
35
|
+
count = GeoserverMigration.all_versions.count
|
36
|
+
puts " --> Database is correctly setup"
|
37
|
+
rescue => e
|
38
|
+
puts " Database is not setup correctly. Did you run rake db:migrate ?"
|
39
|
+
puts " The returned error is #{e.message}"
|
40
|
+
end
|
41
|
+
|
42
|
+
migrator = GeoserverMigrations::Migrator.new
|
43
|
+
if migrator.needs_migration?
|
44
|
+
puts "There are pending migrations."
|
45
|
+
else
|
46
|
+
puts "There are no pending migrations. Geoserver is up to date."
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'geoserver_migrations/migration_proxy'
|
2
|
+
require 'geoserver_migrations/migration'
|
3
|
+
require 'geoserver_migrations/migrator'
|
4
|
+
require 'geoserver_migrations/base'
|
5
|
+
require 'geoserver_migrations/test_connector'
|
6
|
+
require 'geoserver_migrations/api_connector'
|
7
|
+
require 'geoserver_migrations/layer_config'
|
8
|
+
require 'geoserver_migrations/layergroup_config'
|
9
|
+
|
10
|
+
|
11
|
+
module GeoserverMigrations
|
12
|
+
|
13
|
+
#define exceptions
|
14
|
+
|
15
|
+
module ExceptionsMixin
|
16
|
+
def initialize(str)
|
17
|
+
super("GeoserverMigrations: " + str)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
class ArgumentError < ::ArgumentError #:nodoc:
|
21
|
+
include ExceptionsMixin
|
22
|
+
end
|
23
|
+
|
24
|
+
class IllegalMigrationNameError < StandardError #:nodoc:
|
25
|
+
include ExceptionsMixin
|
26
|
+
def initialize(name = nil)
|
27
|
+
if name
|
28
|
+
super("Illegal name for migration file: #{name}\n\t(only lower case letters, numbers, and '_' allowed).")
|
29
|
+
else
|
30
|
+
super("Illegal name for migration.")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def self.migrations_rootpath
|
37
|
+
(!GeoserverMigrations.config.nil? && GeoserverMigrations.config[:migrations_path]) || 'geoserver/migrate'
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.assets_path
|
41
|
+
"#{self.migrations_rootpath}/assets"
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.config
|
45
|
+
::GEOSERVER_MIGRATIONS_CONFIG
|
46
|
+
end
|
47
|
+
|
48
|
+
# class AccessDenied < ::StandardError #:nodoc:
|
49
|
+
# include ExceptionsMixin
|
50
|
+
# def initialize(str='Access denied: you do not have the right permissions for the requested action.')
|
51
|
+
# super(str)
|
52
|
+
# end
|
53
|
+
# end
|
54
|
+
|
55
|
+
|
56
|
+
class Engine < ::Rails::Engine
|
57
|
+
|
58
|
+
# configure our plugin on boot
|
59
|
+
initializer "geoserver_migrations.initialize" do |app|
|
60
|
+
|
61
|
+
# mixin our code ?
|
62
|
+
# ActionController::Base.send(:include, Vigilante::ControllerExtension)
|
63
|
+
# ActiveRecord::Base.send(:include, Vigilante::ActiveRecordExtensions)
|
64
|
+
|
65
|
+
#load configuration files if they are available
|
66
|
+
geoserver_config_file = File.join("#{Rails.root.to_s}", 'config', 'geoserver_migrations_config.yml')
|
67
|
+
|
68
|
+
if File.exist?(geoserver_config_file)
|
69
|
+
Rails.logger.debug "define GEOSERVER_MIGRATIONS_CONFIG"
|
70
|
+
raw_config = File.read(geoserver_config_file)
|
71
|
+
::GEOSERVER_MIGRATIONS_CONFIG = YAML.load(raw_config)["#{Rails.env}"].with_indifferent_access
|
72
|
+
# else
|
73
|
+
# raise GeoserverMigrations::ArgumentError.new("The geoserver_migrations_config.yml is missing. Path=#{geoserver_config_file} Did you run the generator geoserver_migrations:install? ")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
initializer :append_migrations do |app|
|
78
|
+
unless app.root.to_s == root.to_s
|
79
|
+
config.paths["db/migrate"].expanded.each do |expanded_path|
|
80
|
+
app.config.paths["db/migrate"] << expanded_path
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module GeoserverMigrations
|
2
|
+
class APIConnector
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
# initialise geoserver-client
|
6
|
+
GeoserverClient.api_root = ::GEOSERVER_MIGRATIONS_CONFIG[:geoserver_base]
|
7
|
+
GeoserverClient.api_user = ::GEOSERVER_MIGRATIONS_CONFIG[:api][:user]
|
8
|
+
GeoserverClient.api_password = ::GEOSERVER_MIGRATIONS_CONFIG[:api][:password]
|
9
|
+
|
10
|
+
GeoserverClient.workspace = GEOSERVER_MIGRATIONS_CONFIG[:workspace]
|
11
|
+
GeoserverClient.datastore = GEOSERVER_MIGRATIONS_CONFIG[:datastore]
|
12
|
+
# if Rails.present?
|
13
|
+
# GeoserverClient.logger = Rails.logger
|
14
|
+
# end
|
15
|
+
GeoserverClient.logger = :stdout
|
16
|
+
end
|
17
|
+
|
18
|
+
def execute(ordered_actions, direction = :up, options={})
|
19
|
+
if direction != :up
|
20
|
+
ordered_actions = ordered_actions.reverse
|
21
|
+
end
|
22
|
+
|
23
|
+
ordered_actions.each do |action_to_complete|
|
24
|
+
case action_to_complete[:action]
|
25
|
+
when :add_resource
|
26
|
+
file_name = action_to_complete[:params][:name]
|
27
|
+
if direction == :up
|
28
|
+
GeoserverClient.create_resource file_name
|
29
|
+
else
|
30
|
+
GeoserverClient.delete_resource file_name
|
31
|
+
end
|
32
|
+
when :create_layer
|
33
|
+
layer_name = action_to_complete[:params][:name]
|
34
|
+
layer_config = action_to_complete[:params][:layer_config]
|
35
|
+
if direction == :up
|
36
|
+
# explicitly create style if sld given
|
37
|
+
if !layer_config.sld.nil?
|
38
|
+
puts " -- Create style #{layer_config.style_name}"
|
39
|
+
|
40
|
+
GeoserverClient.create_style layer_config.style_name, sld: layer_config.sld
|
41
|
+
end
|
42
|
+
|
43
|
+
puts " -- Create layer #{layer_config.layer_name} [native_name = #{layer_config.feature_name}]"
|
44
|
+
GeoserverClient.create_featuretype layer_name, native_name: layer_config.feature_name
|
45
|
+
GeoserverClient.set_layer_style layer_name, layer_config.style_name
|
46
|
+
else
|
47
|
+
puts " -- delete layer #{layer_config.layer_name}"
|
48
|
+
GeoserverClient.delete_featuretype layer_name
|
49
|
+
|
50
|
+
if !layer_config.sld.nil?
|
51
|
+
puts " -- delete style #{layer_config.style_name}"
|
52
|
+
|
53
|
+
GeoserverClient.delete_style layer_config.style_name
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
when :delete_layer
|
58
|
+
if direction == :up
|
59
|
+
layer_name = action_to_complete[:params][:name]
|
60
|
+
puts " -- Delete layer #{layer_name}"
|
61
|
+
GeoserverClient.delete_featuretype layer_name
|
62
|
+
else
|
63
|
+
# do nothing??
|
64
|
+
# we should save the layer-definition in the :up direction so we can
|
65
|
+
# restore it if needed?
|
66
|
+
end
|
67
|
+
when :delete_style
|
68
|
+
if direction == :up
|
69
|
+
style_name = action_to_complete[:params][:name]
|
70
|
+
puts " -- Delete style #{style_name}"
|
71
|
+
GeoserverClient.delete_style style_name
|
72
|
+
end
|
73
|
+
when :update_style
|
74
|
+
if direction == :up
|
75
|
+
style_name = action_to_complete[:params][:name]
|
76
|
+
layer_config = action_to_complete[:params][:layer_config]
|
77
|
+
puts " -- Updating style #{style_name}"
|
78
|
+
GeoserverClient.update_style style_name, sld: layer_config.sld
|
79
|
+
end
|
80
|
+
when :create_layergroup
|
81
|
+
layer_name = action_to_complete[:params][:name]
|
82
|
+
layer_config = action_to_complete[:params][:layer_config]
|
83
|
+
if direction == :up
|
84
|
+
GeoserverClient.create_layergroup layer_name, layer_config.layers
|
85
|
+
else
|
86
|
+
puts " -- delete layergroup #{layer_config.layer_name}"
|
87
|
+
GeoserverClient.delete_layergroup layer_name
|
88
|
+
end
|
89
|
+
when :delete_layergroup
|
90
|
+
if direction == :up
|
91
|
+
layer_name = action_to_complete[:params][:name]
|
92
|
+
puts " -- Delete layergroup #{layer_name}"
|
93
|
+
GeoserverClient.delete_layergroup layer_name
|
94
|
+
else
|
95
|
+
# do nothing??
|
96
|
+
# we should save the layer-definition in the :up direction so we can
|
97
|
+
# restore it if needed?
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def test
|
105
|
+
layers = GeoserverClient.layers
|
106
|
+
layers["featureTypes"]["featureType"].map{|l| l["name"]}
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'geoserver_migrations/sld_helpers'
|
2
|
+
|
3
|
+
module GeoserverMigrations
|
4
|
+
class LayerConfig
|
5
|
+
|
6
|
+
# attr_writer :sld, :layer_name, :feature_name, :style_name
|
7
|
+
attr_accessor :options
|
8
|
+
|
9
|
+
def initialize(layer_name, is_update_style=false)
|
10
|
+
@options = {
|
11
|
+
layer_name: layer_name,
|
12
|
+
is_update_style: is_update_style
|
13
|
+
}
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
include GeoserverMigrations::SldHelpers
|
18
|
+
|
19
|
+
def valid?
|
20
|
+
# at least feature-name should be present?
|
21
|
+
options[:feature_name].present? || (options[:is_update_style] && options[:sld].present?)
|
22
|
+
end
|
23
|
+
|
24
|
+
def style_name(style_name=nil)
|
25
|
+
if style_name.nil?
|
26
|
+
@options[:style_name] || @options[:layer_name]
|
27
|
+
else
|
28
|
+
@options[:style_name] = style_name
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def method_missing(method,*args,&block)
|
33
|
+
# puts "LayerConfig method-missing: #{method.inspect}, #{args.inspect}"
|
34
|
+
if [:sld, :layer_name, :feature_name, :style_name].include? method.to_sym
|
35
|
+
if args.size > 0
|
36
|
+
value = args.size == 1 ? args.first : args
|
37
|
+
value = value.strip if value.is_a? String
|
38
|
+
@options[method.to_sym] = value
|
39
|
+
else
|
40
|
+
@options[method.to_sym]
|
41
|
+
end
|
42
|
+
else
|
43
|
+
super
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module GeoserverMigrations
|
2
|
+
class LayergroupConfig
|
3
|
+
|
4
|
+
attr_accessor :options
|
5
|
+
|
6
|
+
def initialize(layer_name, is_update_style=false)
|
7
|
+
@options = {
|
8
|
+
layer_name: layer_name,
|
9
|
+
is_update_style: is_update_style,
|
10
|
+
layers: []
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def valid?
|
15
|
+
# at least one layer to be grouped should be present?
|
16
|
+
options[:layers].size > 0
|
17
|
+
end
|
18
|
+
|
19
|
+
def layers(*received_layers)
|
20
|
+
if received_layers.nil?
|
21
|
+
@options[:layers]
|
22
|
+
else
|
23
|
+
if received_layers.is_a? String
|
24
|
+
@options[:layers] = received_layers.split(/[,; ]/).select{|x| !x.empty?}
|
25
|
+
elsif received_layers.is_a? Array
|
26
|
+
received_layers.each do |received_layer|
|
27
|
+
@options[:layers] += received_layer.split(/[,; ]/).select{|x| !x.empty?}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def method_missing(method,*args,&block)
|
34
|
+
# puts "LayerConfig method-missing: #{method.inspect}, #{args.inspect}"
|
35
|
+
if [:layer_name].include? method.to_sym
|
36
|
+
if args.size > 0
|
37
|
+
value = args.size == 1 ? args.first : args
|
38
|
+
value = value.strip if value.is_a? String
|
39
|
+
@options[method.to_sym] = value
|
40
|
+
else
|
41
|
+
@options[method.to_sym]
|
42
|
+
end
|
43
|
+
else
|
44
|
+
super
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module GeoserverMigrations
|
2
|
+
class Migration
|
3
|
+
|
4
|
+
attr_accessor :name, :version, :assets_path
|
5
|
+
|
6
|
+
def initialize(name = self.class.name, version = nil)
|
7
|
+
@name = name
|
8
|
+
@version = version
|
9
|
+
@connection = nil
|
10
|
+
@layers_to_create = {}
|
11
|
+
@layers_to_delete = []
|
12
|
+
@styles_to_delete = []
|
13
|
+
@ordered_actions_to_take = []
|
14
|
+
@assets_path = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def migrate(direction = :up)
|
18
|
+
return unless [:up, :down].include?(direction)
|
19
|
+
|
20
|
+
case direction
|
21
|
+
when :up then announce "migrating"
|
22
|
+
when :down then announce "reverting"
|
23
|
+
end
|
24
|
+
|
25
|
+
time = Benchmark.measure do
|
26
|
+
# collect configuration
|
27
|
+
run
|
28
|
+
|
29
|
+
# puts @layers_to_create.inspect
|
30
|
+
|
31
|
+
# create configured layers
|
32
|
+
GeoserverMigrations::Base.connection.execute(@ordered_actions_to_take, direction)
|
33
|
+
end
|
34
|
+
|
35
|
+
operation = direction == :up ? 'migrated' : 'reverted'
|
36
|
+
announce "#{operation} (%.4fs)" % time.real; write
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def add_resource(resource_name)
|
41
|
+
# translate to full file-name and raise error if not exists?
|
42
|
+
|
43
|
+
full_resource_name = File.join(File.expand_path(self.assets_path), resource_name )
|
44
|
+
|
45
|
+
raise StandardError.new("File #{full_resource_name} not found!") unless File.exists?(full_resource_name)
|
46
|
+
|
47
|
+
@ordered_actions_to_take << {action: :add_resource, params: {name: full_resource_name }}
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_layer(layer_name, &block)
|
51
|
+
layer_config = GeoserverMigrations::LayerConfig.new(layer_name)
|
52
|
+
layer_config.instance_eval(&block) if block_given?
|
53
|
+
if layer_config.valid?
|
54
|
+
@layers_to_create[layer_name] = layer_config
|
55
|
+
@ordered_actions_to_take << {action: :create_layer, params: {name: layer_name, layer_config: layer_config}}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_layergroup(layer_name, &block)
|
60
|
+
layergroup_config = GeoserverMigrations::LayergroupConfig.new(layer_name)
|
61
|
+
layergroup_config.instance_eval(&block) if block_given?
|
62
|
+
if layergroup_config.valid?
|
63
|
+
@layers_to_create[layer_name] = layergroup_config
|
64
|
+
@ordered_actions_to_take << {action: :create_layergroup, params: {name: layer_name, layer_config: layergroup_config}}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def update_style(layer_name, &block)
|
69
|
+
layer_config = GeoserverMigrations::LayerConfig.new(layer_name, true)
|
70
|
+
layer_config.instance_eval(&block) if block_given?
|
71
|
+
if layer_config.valid?
|
72
|
+
@ordered_actions_to_take << {action: :update_style, params: {name: layer_name, layer_config: layer_config}}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def delete_layer(layer_name)
|
77
|
+
@layers_to_delete << layer_name
|
78
|
+
@ordered_actions_to_take << {action: :delete_layer, params: {name: layer_name }}
|
79
|
+
end
|
80
|
+
|
81
|
+
def delete_layergroup(layer_name)
|
82
|
+
@layers_to_delete << layer_name
|
83
|
+
@ordered_actions_to_take << {action: :delete_layergroup, params: {name: layer_name }}
|
84
|
+
end
|
85
|
+
|
86
|
+
def delete_style(style_name)
|
87
|
+
@styles_to_delete << style_name
|
88
|
+
@ordered_actions_to_take << {action: :delete_style, params: {name: style_name }}
|
89
|
+
end
|
90
|
+
|
91
|
+
def write(text = "")
|
92
|
+
puts(text) unless Rails.env.test?
|
93
|
+
end
|
94
|
+
|
95
|
+
def announce(message)
|
96
|
+
text = "#{version} #{name}: #{message}"
|
97
|
+
length = [0, 75 - text.length].max
|
98
|
+
write "== %s %s" % [text, "=" * length]
|
99
|
+
end
|
100
|
+
|
101
|
+
def say(message, subitem = false)
|
102
|
+
write "#{subitem ? " ->" : "--"} #{message}"
|
103
|
+
end
|
104
|
+
|
105
|
+
def say_with_time(message)
|
106
|
+
say(message)
|
107
|
+
result = nil
|
108
|
+
time = Benchmark.measure { result = yield }
|
109
|
+
say "%.4fs" % time.real, :subitem
|
110
|
+
say("#{result} rows", :subitem) if result.is_a?(Integer)
|
111
|
+
result
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module GeoserverMigrations
|
2
|
+
|
3
|
+
# MigrationProxy is used to defer loading of the actual migration classes
|
4
|
+
# until they are needed
|
5
|
+
MigrationProxy = Struct.new(:name, :version, :filename, :scope) do
|
6
|
+
def initialize(name, version, filename, scope)
|
7
|
+
super
|
8
|
+
@migration = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def basename
|
12
|
+
File.basename(filename)
|
13
|
+
end
|
14
|
+
|
15
|
+
def mtime
|
16
|
+
File.mtime filename
|
17
|
+
end
|
18
|
+
|
19
|
+
delegate :migrate, to: :migration
|
20
|
+
delegate :assets_path=, to: :migration
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def migration
|
25
|
+
@migration ||= load_migration
|
26
|
+
end
|
27
|
+
|
28
|
+
def load_migration
|
29
|
+
require(File.expand_path(filename))
|
30
|
+
name.constantize.new(name, version)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module GeoserverMigrations
|
2
|
+
|
3
|
+
class Migrator
|
4
|
+
|
5
|
+
MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/
|
6
|
+
|
7
|
+
def migrate
|
8
|
+
if !any_migrations?
|
9
|
+
puts "No migration files found!"
|
10
|
+
else
|
11
|
+
if !needs_migration?
|
12
|
+
puts "There are no pending migrations."
|
13
|
+
else
|
14
|
+
pending_migrations.each do |migration|
|
15
|
+
migration.assets_path = GeoserverMigrations.assets_path
|
16
|
+
migration.migrate
|
17
|
+
|
18
|
+
GeoserverMigration.set_migrated(migration)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def rollback(steps=1)
|
26
|
+
if steps < 1
|
27
|
+
puts "The nr of steps to rollback has to be at least 1"
|
28
|
+
else
|
29
|
+
rollback_migrations(steps).each do |migration|
|
30
|
+
migration.assets_path = GeoserverMigrations.assets_path
|
31
|
+
migration.migrate(:down)
|
32
|
+
|
33
|
+
GeoserverMigration.set_reverted(migration)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
def get_all_versions
|
41
|
+
begin
|
42
|
+
GeoserverMigration.all_versions.map(&:to_i)
|
43
|
+
rescue
|
44
|
+
[]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def current_version
|
49
|
+
get_all_versions.max || 0
|
50
|
+
end
|
51
|
+
|
52
|
+
def needs_migration?
|
53
|
+
(migrations(migrations_paths).collect(&:version) - get_all_versions).size > 0
|
54
|
+
end
|
55
|
+
|
56
|
+
def any_migrations?
|
57
|
+
migrations(migrations_paths).any?
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def rollback_migrations(steps=1)
|
62
|
+
to_rollback = get_all_versions[0 - steps .. -1]
|
63
|
+
migrations = migrations(migrations_paths)
|
64
|
+
migrations.select { |m| to_rollback.include?(m.version) }
|
65
|
+
end
|
66
|
+
|
67
|
+
def pending_migrations
|
68
|
+
already_migrated = get_all_versions
|
69
|
+
migrations = migrations(migrations_paths)
|
70
|
+
migrations.reject { |m| already_migrated.include?(m.version) }
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
def migrations_paths=(paths)
|
75
|
+
@migrations_paths = paths
|
76
|
+
end
|
77
|
+
|
78
|
+
def migrations_paths
|
79
|
+
@migrations_paths ||= ["geoserver/migrate"]
|
80
|
+
# just to not break things if someone uses: migrations_path = some_string
|
81
|
+
Array(@migrations_paths)
|
82
|
+
end
|
83
|
+
|
84
|
+
def parse_migration_filename(filename) # :nodoc:
|
85
|
+
File.basename(filename).scan(MigrationFilenameRegexp).first
|
86
|
+
end
|
87
|
+
|
88
|
+
def migrations(paths)
|
89
|
+
paths = Array(paths)
|
90
|
+
|
91
|
+
migrations = migration_files(paths).map do |file|
|
92
|
+
version, name, scope = parse_migration_filename(file)
|
93
|
+
raise GeoserverMigrations::IllegalMigrationNameError.new(file) unless version
|
94
|
+
version = version.to_i
|
95
|
+
name = name.camelize
|
96
|
+
|
97
|
+
MigrationProxy.new(name, version, file, scope)
|
98
|
+
end
|
99
|
+
|
100
|
+
migrations.sort_by(&:version)
|
101
|
+
end
|
102
|
+
|
103
|
+
def migration_files(paths)
|
104
|
+
Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,338 @@
|
|
1
|
+
module GeoserverMigrations
|
2
|
+
module SldHelpers
|
3
|
+
|
4
|
+
|
5
|
+
def build_sld_filter(filter_hash)
|
6
|
+
filter_text = ""
|
7
|
+
filters_count = filter_hash.keys.count
|
8
|
+
if filters_count > 0
|
9
|
+
if filters_count == 1
|
10
|
+
filter_text = <<-FILTER
|
11
|
+
<ogc:Filter>
|
12
|
+
<ogc:PropertyIsEqualTo>
|
13
|
+
<ogc:PropertyName>#{filter_hash.keys[0]}</ogc:PropertyName>
|
14
|
+
<ogc:Literal>#{filter_hash.values[0]}</ogc:Literal>
|
15
|
+
</ogc:PropertyIsEqualTo>
|
16
|
+
</ogc:Filter>
|
17
|
+
FILTER
|
18
|
+
elsif filters_count == 2
|
19
|
+
filter_text = <<-FILTER
|
20
|
+
<ogc:Filter>
|
21
|
+
<ogc:And>
|
22
|
+
<ogc:PropertyIsEqualTo>
|
23
|
+
<ogc:PropertyName>#{filter_hash.keys[0]}</ogc:PropertyName>
|
24
|
+
<ogc:Literal>#{filter_hash.values[0]}</ogc:Literal>
|
25
|
+
</ogc:PropertyIsEqualTo>
|
26
|
+
<ogc:PropertyIsEqualTo>
|
27
|
+
<ogc:PropertyName>#{filter_hash.keys[1]}</ogc:PropertyName>
|
28
|
+
<ogc:Literal>#{filter_hash.values[1]}</ogc:Literal>
|
29
|
+
</ogc:PropertyIsEqualTo>
|
30
|
+
</ogc:And>
|
31
|
+
</ogc:Filter>
|
32
|
+
FILTER
|
33
|
+
else
|
34
|
+
raise StandardError.new("Unsupported filter! For now we only support 1 or 2 filter-values :( :(")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
filter_text
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def icon_style_with_label(title, icon_name, icon_style_options={})
|
42
|
+
display_label = icon_style_options[:display_label] || title
|
43
|
+
abstract = icon_style_options[:abstract] || title
|
44
|
+
|
45
|
+
filter_text = ""
|
46
|
+
if icon_style_options[:filter].present? && icon_style_options[:filter].is_a?(Hash)
|
47
|
+
filter_text = build_sld_filter(icon_style_options[:filter])
|
48
|
+
end
|
49
|
+
|
50
|
+
max_scale_text = ""
|
51
|
+
if icon_style_options[:max_scale_denominator].present?
|
52
|
+
max_scale_text = "<MaxScaleDenominator>#{icon_style_options[:max_scale_denominator]}</MaxScaleDenominator>"
|
53
|
+
end
|
54
|
+
|
55
|
+
@options[:sld] = <<-SLD.strip_heredoc
|
56
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
57
|
+
<StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc"
|
58
|
+
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
59
|
+
xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd">
|
60
|
+
<NamedLayer>
|
61
|
+
<Name>#{title}</Name>
|
62
|
+
<UserStyle>
|
63
|
+
<Name>#{title}</Name>
|
64
|
+
<Title>#{title}</Title>
|
65
|
+
<Abstract>#{abstract}</Abstract>
|
66
|
+
<FeatureTypeStyle>
|
67
|
+
<Rule>
|
68
|
+
<Title>#{display_label}</Title>
|
69
|
+
#{filter_text}
|
70
|
+
#{max_scale_text}
|
71
|
+
<PointSymbolizer>
|
72
|
+
<Graphic>
|
73
|
+
<ExternalGraphic>
|
74
|
+
<OnlineResource xlink:type="simple" xlink:href="#{icon_name}" />
|
75
|
+
<Format>image/png</Format>
|
76
|
+
</ExternalGraphic>
|
77
|
+
</Graphic>
|
78
|
+
<VendorOption name="labelObstacle">true</VendorOption>
|
79
|
+
</PointSymbolizer>
|
80
|
+
<TextSymbolizer>
|
81
|
+
<Label>
|
82
|
+
<ogc:PropertyName>name</ogc:PropertyName>
|
83
|
+
</Label>
|
84
|
+
<Font>
|
85
|
+
<CssParameter name="font-family">Arial</CssParameter>
|
86
|
+
<CssParameter name="font-size">11</CssParameter>
|
87
|
+
<CssParameter name="font-style">normal</CssParameter>
|
88
|
+
<CssParameter name="font-weight">bold</CssParameter>
|
89
|
+
</Font>
|
90
|
+
<LabelPlacement>
|
91
|
+
<PointPlacement>
|
92
|
+
<AnchorPoint>
|
93
|
+
<AnchorPointX>0</AnchorPointX>
|
94
|
+
<AnchorPointY>0</AnchorPointY>
|
95
|
+
</AnchorPoint>
|
96
|
+
</PointPlacement>
|
97
|
+
</LabelPlacement>
|
98
|
+
<Halo>
|
99
|
+
<Radius>
|
100
|
+
<ogc:Literal>1</ogc:Literal>
|
101
|
+
</Radius>
|
102
|
+
<Fill>
|
103
|
+
<CssParameter name="fill">#ffffff</CssParameter>
|
104
|
+
</Fill>
|
105
|
+
</Halo>
|
106
|
+
<Fill>
|
107
|
+
<CssParameter name="fill">#2f3133</CssParameter>
|
108
|
+
</Fill>
|
109
|
+
<VendorOption name="maxDisplacement">40</VendorOption>
|
110
|
+
<!--VendorOption name="displacementMode">S, SW, W, NW, N</VendorOption-->
|
111
|
+
<VendorOption name="conflictResolution">true</VendorOption>
|
112
|
+
<VendorOption name="partials">true</VendorOption>
|
113
|
+
</TextSymbolizer>
|
114
|
+
</Rule>
|
115
|
+
</FeatureTypeStyle>
|
116
|
+
</UserStyle>
|
117
|
+
</NamedLayer>
|
118
|
+
</StyledLayerDescriptor>
|
119
|
+
SLD
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
def polygon_style(title, style_options={})
|
125
|
+
display_label = style_options[:display_label] || title
|
126
|
+
abstract = style_options[:abstract] || title
|
127
|
+
|
128
|
+
fill_colour = style_options[:fill_colour] || "#aaaaaa"
|
129
|
+
fill_opacity = style_options[:fill_opacity] || "1"
|
130
|
+
stroke_colour = style_options[:stroke_colour] || "#000000"
|
131
|
+
stroke_width = style_options[:stroke_width] || "1"
|
132
|
+
|
133
|
+
filter_text = ""
|
134
|
+
if style_options[:filter].present? && style_options[:filter].is_a?(Hash)
|
135
|
+
filter_text = build_sld_filter(style_options[:filter])
|
136
|
+
end
|
137
|
+
|
138
|
+
fill_style = ""
|
139
|
+
unless style_options[:no_fill] == true
|
140
|
+
fill_styles = ["<Fill>"]
|
141
|
+
fill_styles << " <CssParameter name=\"fill\">#{fill_colour}</CssParameter>"
|
142
|
+
fill_styles << " <CssParameter name=\"opacity\">#{fill_opacity}</CssParameter>" if style_options[:fill_opacity].present?
|
143
|
+
fill_styles << " </Fill>"
|
144
|
+
fill_style = fill_styles.join("\n")
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
stroke_styles = []
|
149
|
+
stroke_styles << "<Stroke>"
|
150
|
+
stroke_styles << " <CssParameter name=\"stroke\">#{stroke_colour}</CssParameter>"
|
151
|
+
stroke_styles << " <CssParameter name=\"stroke-width\">#{stroke_width}</CssParameter>"
|
152
|
+
|
153
|
+
if style_options[:stroke_dasharray].present?
|
154
|
+
stroke_styles << " <CssParameter name=\"stroke-dasharray\">"
|
155
|
+
stroke_styles << " <ogc:Literal>#{style_options[:stroke_dasharray]}</ogc:Literal>"
|
156
|
+
stroke_styles << " </CssParameter>"
|
157
|
+
end
|
158
|
+
stroke_styles << " </Stroke>"
|
159
|
+
stroke_style = stroke_styles.join("\n")
|
160
|
+
|
161
|
+
max_scale_text = ""
|
162
|
+
if style_options[:max_scale_denominator].present?
|
163
|
+
max_scale_text = "<MaxScaleDenominator>#{style_options[:max_scale_denominator]}</MaxScaleDenominator>"
|
164
|
+
end
|
165
|
+
|
166
|
+
@options[:sld] = <<-SLD.strip_heredoc
|
167
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
168
|
+
<StyledLayerDescriptor version="1.0.0"
|
169
|
+
xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd"
|
170
|
+
xmlns="http://www.opengis.net/sld"
|
171
|
+
xmlns:ogc="http://www.opengis.net/ogc"
|
172
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
173
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
174
|
+
<NamedLayer>
|
175
|
+
<Name>#{title}</Name>
|
176
|
+
<UserStyle>
|
177
|
+
<Name>#{title}</Name>
|
178
|
+
<Title>#{title}</Title>
|
179
|
+
<Abstract>#{abstract}</Abstract>
|
180
|
+
<FeatureTypeStyle>
|
181
|
+
<Rule>
|
182
|
+
<Title>#{display_label}</Title>
|
183
|
+
#{filter_text}
|
184
|
+
#{max_scale_text}
|
185
|
+
<PolygonSymbolizer>
|
186
|
+
#{fill_style}
|
187
|
+
#{stroke_style}
|
188
|
+
</PolygonSymbolizer>
|
189
|
+
</Rule>
|
190
|
+
</FeatureTypeStyle>
|
191
|
+
</UserStyle>
|
192
|
+
</NamedLayer>
|
193
|
+
</StyledLayerDescriptor>
|
194
|
+
SLD
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
def line_style(title, style_options={})
|
200
|
+
display_label = style_options[:display_label] || title
|
201
|
+
abstract = style_options[:abstract] || title
|
202
|
+
|
203
|
+
stroke_colour = style_options[:stroke_colour] || "#000000"
|
204
|
+
stroke_width = style_options[:stroke_width] || "1"
|
205
|
+
|
206
|
+
|
207
|
+
filter_text = ""
|
208
|
+
if style_options[:filter].present? && style_options[:filter].is_a?(Hash)
|
209
|
+
filter_text = build_sld_filter(style_options[:filter])
|
210
|
+
end
|
211
|
+
|
212
|
+
max_scale_text = ""
|
213
|
+
if style_options[:max_scale_denominator].present?
|
214
|
+
max_scale_text = "<MaxScaleDenominator>#{style_options[:max_scale_denominator]}</MaxScaleDenominator>"
|
215
|
+
end
|
216
|
+
|
217
|
+
@options[:sld] = <<-SLD.strip_heredoc
|
218
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
219
|
+
<StyledLayerDescriptor version="1.0.0"
|
220
|
+
xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd"
|
221
|
+
xmlns="http://www.opengis.net/sld"
|
222
|
+
xmlns:ogc="http://www.opengis.net/ogc"
|
223
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
224
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
225
|
+
<NamedLayer>
|
226
|
+
<Name>#{title}</Name>
|
227
|
+
<UserStyle>
|
228
|
+
<Name>#{title}</Name>
|
229
|
+
<Title>#{title}</Title>
|
230
|
+
<Abstract>#{abstract}</Abstract>
|
231
|
+
<FeatureTypeStyle>
|
232
|
+
<Rule>
|
233
|
+
<Title>#{display_label}</Title>
|
234
|
+
#{filter_text}
|
235
|
+
#{max_scale_text}
|
236
|
+
<LineSymbolizer>
|
237
|
+
<Stroke>
|
238
|
+
<CssParameter name="stroke">#{stroke_colour}</CssParameter>
|
239
|
+
<CssParameter name="stroke-width">#{stroke_width}</CssParameter>
|
240
|
+
</Stroke>
|
241
|
+
</LineSymbolizer>
|
242
|
+
</Rule>
|
243
|
+
</FeatureTypeStyle>
|
244
|
+
</UserStyle>
|
245
|
+
</NamedLayer>
|
246
|
+
</StyledLayerDescriptor>
|
247
|
+
SLD
|
248
|
+
|
249
|
+
end
|
250
|
+
|
251
|
+
# def polygon_style_with_label(title, style_options={})
|
252
|
+
# display_label = icon_style_options[:display_label] || title
|
253
|
+
# abstract = icon_style_options[:abstract] || title
|
254
|
+
#
|
255
|
+
#
|
256
|
+
#
|
257
|
+
#
|
258
|
+
# @options[:sld] = <<-SLD
|
259
|
+
# <?xml version="1.0" encoding="ISO-8859-1"?>
|
260
|
+
# <StyledLayerDescriptor version="1.0.0"
|
261
|
+
# xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd"
|
262
|
+
# xmlns="http://www.opengis.net/sld"
|
263
|
+
# xmlns:ogc="http://www.opengis.net/ogc"
|
264
|
+
# xmlns:xlink="http://www.w3.org/1999/xlink"
|
265
|
+
# xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
266
|
+
# <NamedLayer>
|
267
|
+
# <Name>#{title}</Name>
|
268
|
+
# <UserStyle>
|
269
|
+
# <Title>#{title}</Title>
|
270
|
+
# <Abstract>#{abstract}</Abstract>
|
271
|
+
# <FeatureTypeStyle>
|
272
|
+
# <Rule>
|
273
|
+
# <Title>#{display_label}</Title>
|
274
|
+
# <MinScaleDenominator>10000</MinScaleDenominator>
|
275
|
+
# <MaxScaleDenominator>200000</MaxScaleDenominator>
|
276
|
+
# <PolygonSymbolizer>
|
277
|
+
# <Fill>
|
278
|
+
# <CssParameter name="fill">#AAAAAA</CssParameter>
|
279
|
+
# <CssParameter name="fill-opacity">0.3</CssParameter>
|
280
|
+
# </Fill>
|
281
|
+
# <Stroke>
|
282
|
+
# <CssParameter name="stroke">#FFFFFF</CssParameter>
|
283
|
+
# <CssParameter name="stroke-width">3</CssParameter>
|
284
|
+
# </Stroke>
|
285
|
+
# </PolygonSymbolizer>
|
286
|
+
# </Rule>
|
287
|
+
# <Rule>
|
288
|
+
# <Name>rule2</Name>
|
289
|
+
# <Title>Beheerkaart ingezoomed</Title>
|
290
|
+
# <Abstract>A polygon with a gray fill and a 3 pixel while outline and a label indicating the name</Abstract>
|
291
|
+
# <MaxScaleDenominator>10000</MaxScaleDenominator>
|
292
|
+
# <PolygonSymbolizer>
|
293
|
+
# <Fill>
|
294
|
+
# <CssParameter name="fill">#AAAAAA</CssParameter>
|
295
|
+
# <CssParameter name="fill-opacity">0.3</CssParameter>
|
296
|
+
# </Fill>
|
297
|
+
# <Stroke>
|
298
|
+
# <CssParameter name="stroke">#FFFFFF</CssParameter>
|
299
|
+
# <CssParameter name="stroke-width">3</CssParameter>
|
300
|
+
# </Stroke>
|
301
|
+
# </PolygonSymbolizer>
|
302
|
+
# <TextSymbolizer>
|
303
|
+
# <Geometry>
|
304
|
+
# <ogc:Function name="centroid">
|
305
|
+
# <ogc:PropertyName>geom</ogc:PropertyName>
|
306
|
+
# </ogc:Function>
|
307
|
+
# </Geometry>
|
308
|
+
# <Label>
|
309
|
+
# <ogc:PropertyName>name</ogc:PropertyName>
|
310
|
+
# </Label>
|
311
|
+
# <Font>
|
312
|
+
# <CssParameter name="font-family">Arial</CssParameter>
|
313
|
+
# <CssParameter name="font-size">18</CssParameter>
|
314
|
+
# <CssParameter name="font-style">normal</CssParameter>
|
315
|
+
# <CssParameter name="font-weight">bold</CssParameter>
|
316
|
+
# </Font>
|
317
|
+
# <Halo>
|
318
|
+
# <Radius>2</Radius>
|
319
|
+
# <Fill>
|
320
|
+
# <CssParameter name="fill">#FFFFFF</CssParameter>
|
321
|
+
# </Fill>
|
322
|
+
# </Halo>
|
323
|
+
# <Fill>
|
324
|
+
# <CssParameter name="fill">#000</CssParameter>
|
325
|
+
# </Fill>
|
326
|
+
# </TextSymbolizer>
|
327
|
+
# </Rule>
|
328
|
+
# </FeatureTypeStyle>
|
329
|
+
# </UserStyle>
|
330
|
+
# </NamedLayer>
|
331
|
+
# </StyledLayerDescriptor>
|
332
|
+
#
|
333
|
+
# SLD
|
334
|
+
#
|
335
|
+
# end
|
336
|
+
|
337
|
+
end
|
338
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module GeoserverMigrations
|
2
|
+
class TestConnector
|
3
|
+
|
4
|
+
attr_accessor :collected_actions
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@collected_actions = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def execute(layer_configs, direction=:up, options={})
|
11
|
+
collected_actions.merge!(direction => layer_configs)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: geoserver_migrations
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "'nathanvda'"
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-05-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.2.7
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.2.7
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sqlite3
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.7'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.7'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-rails
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.7'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.7'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simplecov
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: 'Manage your geoserver configuration like you manage your database: with
|
84
|
+
migrations'
|
85
|
+
email:
|
86
|
+
- "'nathan@dixis.com'"
|
87
|
+
executables: []
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- Rakefile
|
92
|
+
- app/models/geoserver_migration.rb
|
93
|
+
- db/migrate/20180104170500_create_geoserver_migrations.rb
|
94
|
+
- lib/generators/geoserver_migrations/add/add_generator.rb
|
95
|
+
- lib/generators/geoserver_migrations/add/templates/migration_template.rb
|
96
|
+
- lib/generators/geoserver_migrations/install/install_generator.rb
|
97
|
+
- lib/generators/geoserver_migrations/install/templates/geoserver_migrations_config.yml
|
98
|
+
- lib/generators/geoserver_migrations/migrate/migrate_generator.rb
|
99
|
+
- lib/generators/geoserver_migrations/redo/redo_generator.rb
|
100
|
+
- lib/generators/geoserver_migrations/rollback/rollback_generator.rb
|
101
|
+
- lib/generators/geoserver_migrations/status/status_generator.rb
|
102
|
+
- lib/geoserver_migrations.rb
|
103
|
+
- lib/geoserver_migrations/api_connector.rb
|
104
|
+
- lib/geoserver_migrations/base.rb
|
105
|
+
- lib/geoserver_migrations/layer_config.rb
|
106
|
+
- lib/geoserver_migrations/layergroup_config.rb
|
107
|
+
- lib/geoserver_migrations/migration.rb
|
108
|
+
- lib/geoserver_migrations/migration_proxy.rb
|
109
|
+
- lib/geoserver_migrations/migrator.rb
|
110
|
+
- lib/geoserver_migrations/sld_helpers.rb
|
111
|
+
- lib/geoserver_migrations/test_connector.rb
|
112
|
+
- lib/geoserver_migrations/version.rb
|
113
|
+
- lib/tasks/geoserver_migrations_tasks.rake
|
114
|
+
homepage: https://github.com/nathanvda/geoserver_migrations
|
115
|
+
licenses:
|
116
|
+
- MIT
|
117
|
+
metadata: {}
|
118
|
+
post_install_message:
|
119
|
+
rdoc_options: []
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
requirements: []
|
133
|
+
rubyforge_project:
|
134
|
+
rubygems_version: 2.2.2
|
135
|
+
signing_key:
|
136
|
+
specification_version: 4
|
137
|
+
summary: manage your geoserver configuration using migrations
|
138
|
+
test_files: []
|