geoserver_migrations 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|