geoserver_client 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e6a9f28cade0ce095bbd1ad4d09d73836148d8a8
4
+ data.tar.gz: 384ff7caa3ba8d0a4161b7e3807e303d03e060b1
5
+ SHA512:
6
+ metadata.gz: d6b09d218d116a1e8556e896d5172ddb05363e0389364a2f87b7e196d6f90d760dcf76b3bc4d75534c7a22fa1c025f01df32eec8a7a83b31f8a4737ba7c911c1
7
+ data.tar.gz: 216b48d8f3e70eeb209c562b4657bdd52e8933fd264f513fa303f7dc88b91b8b730182fd073f906b407e57e17ad7066e6760d7230de1a3b20ba7830ebe8d3325
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,46 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ ## Our Standards
8
+
9
+ Examples of behavior that contributes to creating a positive environment include:
10
+
11
+ * Using welcoming and inclusive language
12
+ * Being respectful of differing viewpoints and experiences
13
+ * Gracefully accepting constructive criticism
14
+ * Focusing on what is best for the community
15
+ * Showing empathy towards other community members
16
+
17
+ Examples of unacceptable behavior by participants include:
18
+
19
+ * The use of sexualized language or imagery and unwelcome sexual attention or advances
20
+ * Trolling, insulting/derogatory comments, and personal or political attacks
21
+ * Public or private harassment
22
+ * Publishing others' private information, such as a physical or electronic address, without explicit permission
23
+ * Other conduct which could reasonably be considered inappropriate in a professional setting
24
+
25
+ ## Our Responsibilities
26
+
27
+ Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28
+
29
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30
+
31
+ ## Scope
32
+
33
+ This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34
+
35
+ ## Enforcement
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at nathan(at)dixis.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38
+
39
+ Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40
+
41
+ ## Attribution
42
+
43
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44
+
45
+ [homepage]: http://contributor-covenant.org
46
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "https://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+
4
+ gem 'httpclient'
5
+
6
+
7
+ # Add dependencies to develop your gem here.
8
+ # Include everything needed to run rake, tests, features, etc.
9
+ group :development do
10
+ gem "rspec", "~> 3.5.0"
11
+ gem "rdoc", "~> 3.12"
12
+ gem "bundler", "~> 1.0"
13
+ gem "juwelier", "~> 2.1.0"
14
+ gem "simplecov", ">= 0"
15
+ end
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2018 'nathanvda'
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,27 @@
1
+ # geoserver_client
2
+
3
+ > A simple gem to control your GeoServer installation using the REST API
4
+
5
+ ## Introduction
6
+
7
+ There is a very good gem to interact with the GeoServer API: [rgeoserver](https://github.com/sul-dlss/rgeoserver)
8
+ which I decided not to use because I wanted a more light-weight, simpler alternative and I prefer to use
9
+ HttpClient in general.
10
+
11
+ This gem was created for my own limited interactions with GeoServer and the `geoserver_migrations` gem.
12
+
13
+
14
+ This is, for now, a very naive approach to writing an API client, but it allowed me to discover how the Geoserver API
15
+ worked and gets the job done for me (controlling layer/style management).
16
+
17
+
18
+ ## Todo
19
+
20
+ * add tests :)
21
+ * add more API entries?
22
+ *
23
+
24
+
25
+ ## Copyright
26
+
27
+ Copyright (c) 2018 Nathan Van der Auwera. See LICENSE.txt for further details.
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+ require 'juwelier'
14
+ Juwelier::Tasks.new do |gem|
15
+ # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
16
+ gem.name = "geoserver_client"
17
+ gem.homepage = "http://github.com/nathanvda/geoserver_client"
18
+ gem.license = "MIT"
19
+ gem.summary = %Q{Simple GeoServer API client}
20
+ gem.description = %Q{Simple procedural client to consume the GeoServer REST API}
21
+ gem.email = "'nathan@dixis.com'"
22
+ gem.authors = ["Nathan Van der Auwera"]
23
+
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Juwelier::RubygemsDotOrgTasks.new
27
+ require 'rspec/core'
28
+ require 'rspec/core/rake_task'
29
+ RSpec::Core::RakeTask.new(:spec) do |spec|
30
+ spec.pattern = FileList['spec/**/*_spec.rb']
31
+ end
32
+
33
+ desc "Code coverage detail"
34
+ task :simplecov do
35
+ ENV['COVERAGE'] = "true"
36
+ Rake::Task['spec'].execute
37
+ end
38
+
39
+ task :default => :spec
40
+
41
+ require 'rdoc/task'
42
+ Rake::RDocTask.new do |rdoc|
43
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = "geoserver_client #{version}"
47
+ rdoc.rdoc_files.include('README*')
48
+ rdoc.rdoc_files.include('lib/**/*.rb')
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
@@ -0,0 +1,136 @@
1
+ # configure geoserver-client
2
+ require "base64"
3
+ require "json"
4
+ require_relative '../lib/geoserver_client'
5
+
6
+ GeoserverClient.api_root = "http://localhost:8080/geoserver/rest/"
7
+ GeoserverClient.api_user = "admin"
8
+ GeoserverClient.api_password = "YOUR_SECRET_PASSWORD"
9
+
10
+ GeoserverClient.workspace = 'YOUR_WORKSPACE'
11
+ GeoserverClient.datastore = 'YOUR_DATASTORE'
12
+
13
+ GeoserverClient.logger = :stdout
14
+
15
+
16
+ # puts GeoserverClient.delete_layergroup("masterdata_2", true)
17
+ # puts GeoserverClient.create_layergroup("masterdata_2", ["sabic:pipelines", "sabic:cables"], {}, true)
18
+ #
19
+ # puts GeoserverClient.layergroups(true)
20
+ #
21
+ # puts GeoserverClient.get_layergroup("masterdata", true )
22
+ #
23
+ # puts GeoserverClient.layergroups(true)
24
+ #
25
+ # puts GeoserverClient.delete_layergroup("masterdata", true)
26
+ # puts GeoserverClient.delete_layergroup("masterdata_2", true)
27
+ #
28
+
29
+
30
+ # create an sld for test
31
+
32
+ welds_sld = <<-SLD
33
+ <?xml version="1.0" encoding="ISO-8859-1"?>
34
+ <StyledLayerDescriptor version="1.0.0"
35
+ xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd"
36
+ xmlns="http://www.opengis.net/sld"
37
+ xmlns:ogc="http://www.opengis.net/ogc"
38
+ xmlns:xlink="http://www.w3.org/1999/xlink"
39
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
40
+ <!-- a Named Layer is the basic building block of an SLD document -->
41
+ <NamedLayer>
42
+ <Name>default_point</Name>
43
+ <UserStyle>
44
+ <!-- Styles can have names, titles and abstracts -->
45
+ <Title>Default Point</Title>
46
+ <Abstract>A sample style that draws a point</Abstract>
47
+ <!-- FeatureTypeStyles describe how to render different features -->
48
+ <!-- A FeatureTypeStyle for rendering points -->
49
+ <FeatureTypeStyle>
50
+ <Rule>
51
+ <Name>rule1</Name>
52
+ <Title>Green circle</Title>
53
+ <Abstract>A 6 pixel circle with a red fill and no stroke</Abstract>
54
+ <MinScaleDenominator>1000</MinScaleDenominator>
55
+ <MaxScaleDenominator>2500</MaxScaleDenominator>
56
+ <PointSymbolizer>
57
+ <Graphic>
58
+ <Mark>
59
+ <WellKnownName>circle</WellKnownName>
60
+ <Fill>
61
+ <CssParameter name="fill">#00FF00</CssParameter>
62
+ </Fill>
63
+ </Mark>
64
+ <Size>6</Size>
65
+ </Graphic>
66
+ </PointSymbolizer>
67
+ </Rule>
68
+ <Rule>
69
+ <Name>rule2</Name>
70
+ <Title>Green circle with label</Title>
71
+ <Abstract>A 6 pixel circle with a red fill and no stroke, and a label</Abstract>
72
+ <MaxScaleDenominator>1000</MaxScaleDenominator>
73
+ <PointSymbolizer>
74
+ <Graphic>
75
+ <Mark>
76
+ <WellKnownName>circle</WellKnownName>
77
+ <Fill>
78
+ <CssParameter name="fill">#00FF00</CssParameter>
79
+ </Fill>
80
+ </Mark>
81
+ <Size>6</Size>
82
+ </Graphic>
83
+ </PointSymbolizer>
84
+ <TextSymbolizer>
85
+ <Label>
86
+ <ogc:PropertyName>name</ogc:PropertyName>
87
+ </Label>
88
+ <Font>
89
+ <CssParameter name="font-family">Arial</CssParameter>
90
+ <CssParameter name="font-size">12</CssParameter>
91
+ <CssParameter name="font-style">normal</CssParameter>
92
+ <CssParameter name="font-weight">bold</CssParameter>
93
+ </Font>
94
+ <LabelPlacement>
95
+ <PointPlacement>
96
+ <AnchorPoint>
97
+ <AnchorPointX>0.1</AnchorPointX>
98
+ <AnchorPointY>0.0</AnchorPointY>
99
+ </AnchorPoint>
100
+ <Displacement>
101
+ <DisplacementX>0</DisplacementX>
102
+ <DisplacementY>5</DisplacementY>
103
+ </Displacement>
104
+ <Rotation>-45</Rotation>
105
+ </PointPlacement>
106
+ </LabelPlacement>
107
+ <Fill>
108
+ <CssParameter name="fill">#000000</CssParameter>
109
+ </Fill>
110
+ <VendorOption name="conflictResolution">false</VendorOption>
111
+ <VendorOption name="partials">true</VendorOption>
112
+ </TextSymbolizer>
113
+ </Rule>
114
+ </FeatureTypeStyle>
115
+ </UserStyle>
116
+ </NamedLayer>
117
+ </StyledLayerDescriptor>
118
+
119
+ SLD
120
+
121
+
122
+ # Lets assume we have a table called welds in the datastore and create a layer for it
123
+
124
+ puts GeoserverClient.delete_style("test_welds", true )
125
+ puts GeoserverClient.delete_featuretype("test_welds", true )
126
+
127
+ puts GeoserverClient.create_style("test_welds", {sld: welds_sld}, true )
128
+ puts GeoserverClient.create_featuretype("test_welds", {style_name: "test_welds", native_name: "welds"}, true)
129
+ # puts GeoserverClient.set_layer_style("test_welds", {style_name: "test_welds", native_name: "welds"}, true)
130
+
131
+ # puts GeoserverClient.delete_style("heli_trees")
132
+
133
+
134
+ file_name = File.join(File.expand_path(File.dirname(__FILE__)), "rapl_zakbaken_s.png")
135
+ puts GeoserverClient.create_resource(file_name)
136
+ # puts GeoserverClient.delete_resource(file_name)
@@ -0,0 +1,69 @@
1
+ # Generated by juwelier
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: geoserver_client 0.0.2 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "geoserver_client".freeze
9
+ s.version = "0.0.2"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib".freeze]
13
+ s.authors = ["Nathan Van der Auwera".freeze]
14
+ s.date = "2019-05-07"
15
+ s.description = "Simple procedural client to consume the GeoServer REST API".freeze
16
+ s.email = "'nathan@dixis.com'".freeze
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".rspec",
24
+ "CODE_OF_CONDUCT.md",
25
+ "Gemfile",
26
+ "LICENSE.txt",
27
+ "README.md",
28
+ "Rakefile",
29
+ "VERSION",
30
+ "examples/rapl_zakbaken_s.png",
31
+ "examples/test_geoserver_api.rb",
32
+ "geoserver_client.gemspec",
33
+ "lib/geoserver_client.rb",
34
+ "spec/geoserver_client_spec.rb",
35
+ "spec/spec_helper.rb"
36
+ ]
37
+ s.homepage = "http://github.com/nathanvda/geoserver_client".freeze
38
+ s.licenses = ["MIT".freeze]
39
+ s.rubygems_version = "2.6.11".freeze
40
+ s.summary = "Simple GeoServer API client".freeze
41
+
42
+ if s.respond_to? :specification_version then
43
+ s.specification_version = 4
44
+
45
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
46
+ s.add_runtime_dependency(%q<httpclient>.freeze, [">= 0"])
47
+ s.add_development_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
48
+ s.add_development_dependency(%q<rdoc>.freeze, ["~> 3.12"])
49
+ s.add_development_dependency(%q<bundler>.freeze, ["~> 1.0"])
50
+ s.add_development_dependency(%q<juwelier>.freeze, ["~> 2.1.0"])
51
+ s.add_development_dependency(%q<simplecov>.freeze, [">= 0"])
52
+ else
53
+ s.add_dependency(%q<httpclient>.freeze, [">= 0"])
54
+ s.add_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
55
+ s.add_dependency(%q<rdoc>.freeze, ["~> 3.12"])
56
+ s.add_dependency(%q<bundler>.freeze, ["~> 1.0"])
57
+ s.add_dependency(%q<juwelier>.freeze, ["~> 2.1.0"])
58
+ s.add_dependency(%q<simplecov>.freeze, [">= 0"])
59
+ end
60
+ else
61
+ s.add_dependency(%q<httpclient>.freeze, [">= 0"])
62
+ s.add_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
63
+ s.add_dependency(%q<rdoc>.freeze, ["~> 3.12"])
64
+ s.add_dependency(%q<bundler>.freeze, ["~> 1.0"])
65
+ s.add_dependency(%q<juwelier>.freeze, ["~> 2.1.0"])
66
+ s.add_dependency(%q<simplecov>.freeze, [">= 0"])
67
+ end
68
+ end
69
+
@@ -0,0 +1,369 @@
1
+ require 'httpclient'
2
+ require 'httpclient/include_client'
3
+
4
+
5
+ class GeoserverClient
6
+
7
+ extend HTTPClient::IncludeClient
8
+ include_http_client do |client|
9
+ client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
10
+ end
11
+
12
+
13
+ class ConfigException < StandardError
14
+
15
+ end
16
+
17
+ def self.api_user
18
+ @@api_user ||= "admin"
19
+ end
20
+
21
+ def self.api_password
22
+ @@api_password ||= "geoserver"
23
+ end
24
+
25
+ def self.api_root
26
+ @@api_root ||= ""
27
+ end
28
+
29
+ def self.api_user=(api_user)
30
+ @@api_user = api_user
31
+ end
32
+
33
+ def self.api_password=(api_password)
34
+ @@api_password = api_password
35
+ end
36
+
37
+ def self.api_root= (api_root)
38
+ api_root += "/" if !api_root.nil? && api_root[-1] != "/"
39
+ @@api_root = api_root
40
+ end
41
+
42
+ def self.workspace
43
+ raise ConfigException.new('GeoserverClient::workspace is not yet set') if @@default_workspace.nil?
44
+ @@default_workspace
45
+ end
46
+
47
+ def self.datastore
48
+ raise ConfigException.new('GeoserverClient::datastore is not yet set') if @@default_datastore.nil?
49
+ @@default_datastore
50
+ end
51
+
52
+ def self.workspace=(other_workspace)
53
+ @@default_workspace = other_workspace
54
+ end
55
+
56
+ def self.datastore=(other_datastore)
57
+ @@default_datastore = other_datastore
58
+ end
59
+
60
+ def self.logger
61
+ @@logger rescue nil
62
+ end
63
+
64
+ def self.logger=(other_logger)
65
+ @@logger = other_logger
66
+ end
67
+
68
+ def self.log(message, loglevel=:debug )
69
+ return if logger.nil?
70
+ if logger.respond_to?(loglevel)
71
+ logger.send loglevel, "GeoserverClient::#{message}"
72
+ elsif logger == :stdout
73
+ puts message
74
+ end
75
+ end
76
+
77
+
78
+
79
+ def self.all_layer_names(debug_mode=false)
80
+ all_layers_data = self.all_layers(debug_mode)
81
+ all_layers_data["featureTypes"]["featureType"].map{|x| x["name"]}
82
+ end
83
+
84
+
85
+ def self.all_layers(debug_mode=false)
86
+ log "Get all layers in workspace #{self.workspace}"
87
+
88
+ puts "workspace = #{self.workspace}"
89
+
90
+ get_feature_types_uri = URI.join(GeoserverClient.api_root, "workspaces/#{self.workspace}/featuretypes.json" )
91
+ get_data(get_feature_types_uri, {}, debug_mode )
92
+ end
93
+
94
+
95
+ def self.layers(debug_mode=false)
96
+ log "Get layers in datastore #{self.datastore}"
97
+
98
+ get_feature_types_uri = URI.join(GeoserverClient.api_root, "workspaces/#{self.workspace}/datastores/#{self.datastore}/featuretypes.json" )
99
+ get_data(get_feature_types_uri, {}, debug_mode )
100
+ end
101
+
102
+ def self.feature_type(layer_name, debug_mode=false)
103
+ log "Get layer #{layer_name} in datastore #{self.datastore}"
104
+
105
+ get_feature_type_uri = URI.join(GeoserverClient.api_root, "workspaces/#{self.workspace}/datastores/#{self.datastore}/featuretypes/#{layer_name}.json" )
106
+ get_data(get_feature_type_uri, {}, debug_mode )
107
+ end
108
+
109
+ def self.layer(layer_name, debug_mode=false)
110
+ log "Get layer #{layer_name} in datastore #{self.datastore}"
111
+
112
+ get_feature_type_uri = URI.join(GeoserverClient.api_root, "workspaces/#{self.workspace}/datastores/#{self.datastore}/layers/#{layer_name}.json" )
113
+ get_data(get_feature_type_uri, {}, debug_mode )
114
+ end
115
+
116
+ def self.create_featuretype(name, options={}, debug_mode=false)
117
+ data = {
118
+ featureType: {
119
+ name: name,
120
+ nativeName: options[:native_name] || name,
121
+ # title: options[:title],
122
+ # abstract: options[:abstract],
123
+ # store: {
124
+ # "@class" => "dataStore",
125
+ # name: self.datastore
126
+ # },
127
+ # projectionPolicy: options[:projection_policy] || "FORCE_DECLARED",
128
+ # srs: options[:srs] || "EPSG:3035",
129
+ # # more options
130
+ }
131
+ }
132
+
133
+
134
+
135
+ create_featuretype_uri = URI.join(GeoserverClient.api_root, "workspaces/#{self.workspace}/datastores/#{self.datastore}/featuretypes.json" )
136
+ post_data create_featuretype_uri, data.to_json, debug_mode
137
+ end
138
+
139
+
140
+ def self.delete_featuretype(name, debug_mode=false)
141
+ delete_featuretype_uri = URI.join(GeoserverClient.api_root, "workspaces/#{self.workspace}/datastores/#{self.datastore}/featuretypes/#{name}.json?recurse=true" )
142
+ response = post_data(delete_featuretype_uri, {}, debug_mode, method: :delete )
143
+ end
144
+
145
+
146
+
147
+ # def self.create_layer(layer_name, options={}, debug_mode=false)
148
+ # data = {featureType: {
149
+ # name: layer_name,
150
+ # native_name: options[:native_name] || layer_name,
151
+ # title: options[:title],
152
+ # abstract: options[:abstract],
153
+ #
154
+ #
155
+ # }}
156
+ #
157
+ # update_layer_uri = URI.join(GeoserverClient.api_root, "layers/#{self.workspace}:#{layer_name}.json" )
158
+ # post_data update_layer_uri, data, debug_mode, method: :put
159
+ #
160
+ # end
161
+
162
+
163
+ def self.set_layer_style(layer_name, style_name, debug_mode=false)
164
+ data = {layer: {defaultStyle: style_name }}
165
+
166
+ update_layer_uri = URI.join(GeoserverClient.api_root, "layers/#{self.workspace}:#{layer_name}.json" )
167
+ post_data update_layer_uri, data.to_json, debug_mode, method: :put
168
+ end
169
+
170
+ def self.styles(debug_mode=false)
171
+ log "Geoserver::Get styles in datastore #{self.datastore}"
172
+
173
+ get_styles_uri = URI.join(GeoserverClient.api_root, "styles.json" )
174
+ get_data(get_styles_uri, {}, debug_mode )
175
+ end
176
+
177
+ def self.style(style_name, format=:sld, debug_mode=false)
178
+ log "Geoserver::Get styles in datastore #{self.datastore}"
179
+
180
+ get_styles_uri = URI.join(GeoserverClient.api_root, "styles/#{style_name}.#{format}" )
181
+ get_data(get_styles_uri, {}, debug_mode )
182
+ end
183
+
184
+ def self.create_style(name, options={}, debug_mode=false)
185
+ filename = options[:filename] || "#{name}.sld"
186
+
187
+ # raise exception if filename does not end in sld?
188
+
189
+ data = { style:
190
+ {
191
+ name: name,
192
+ filename: filename
193
+ }
194
+ }
195
+ create_style_uri = URI.join(GeoserverClient.api_root, "styles.json" )
196
+ response = post_data(create_style_uri, data.to_json, debug_mode)
197
+
198
+ if options[:sld].present?
199
+ post_sld_uri = URI.join(GeoserverClient.api_root, "styles/#{filename}" )
200
+ response = post_data(post_sld_uri, options[:sld], debug_mode, method: :put, content_type: 'application/vnd.ogc.sld+xml')
201
+ end
202
+
203
+ response
204
+ end
205
+
206
+ def self.update_style(name, options={}, debug_mode=false)
207
+ filename = options[:filename] || "#{name}.sld"
208
+
209
+ # raise exception if filename does not end in sld?
210
+
211
+ if options[:sld].present?
212
+ post_sld_uri = URI.join(GeoserverClient.api_root, "styles/#{filename}" )
213
+ response = post_data(post_sld_uri, options[:sld], debug_mode, method: :put, content_type: 'application/vnd.ogc.sld+xml')
214
+ else
215
+ raise StandardError.new("SLD parameter was missing!")
216
+ end
217
+
218
+ response
219
+ end
220
+
221
+
222
+
223
+ def self.delete_style(name, debug_mode = false)
224
+ delete_style_uri = URI.join(GeoserverClient.api_root, "styles/#{name}.json" )
225
+ response = post_data(delete_style_uri, {}, debug_mode, method: :delete )
226
+ end
227
+
228
+
229
+ def self.create_resource(file_name, options={}, debug_mode=false)
230
+ # check if the file exists?
231
+ raise StandardError.new("Given file #{file_name} does not exist?") unless File.exist?(file_name)
232
+
233
+ basename = File.basename(file_name)
234
+ file_data = File.read(file_name)
235
+
236
+
237
+ create_resource_uri = URI.join(GeoserverClient.api_root, "resource/styles/", basename, "?operation=default" )
238
+
239
+ puts "Create resource uri = #{create_resource_uri}"
240
+
241
+ response = post_data(create_resource_uri, file_data, debug_mode, method: :put, content_type: '*/*')
242
+ response
243
+ end
244
+
245
+ def self.delete_resource(file_name, options={}, debug_mode=false)
246
+
247
+ basename = File.basename(file_name)
248
+
249
+ # deleting will delete folder recursively, but how can we check/protect this?
250
+
251
+ delete_resource_uri = URI.join(GeoserverClient.api_root, "resource/", basename )
252
+
253
+ puts "Delete resource uri = #{delete_resource_uri}"
254
+
255
+ response = post_data(delete_resource_uri, {}, debug_mode, method: :delete)
256
+ response
257
+ end
258
+
259
+
260
+ def self.create_layergroup(layer_group_name, layers, options= {}, debug_mode = false)
261
+ log "Geoserver::Create layer-group #{layer_group_name} in datastore #{self.datastore}"
262
+
263
+ data = { layerGroup: {
264
+ name: layer_group_name,
265
+ mode: "SINGLE",
266
+ workspace: { name: GeoserverClient.workspace },
267
+ publishables: {published:[]}
268
+ }
269
+ }
270
+
271
+ layers.each do |layer|
272
+ layer_data = {"@type" => "layer", "name" => layer}
273
+ data[:layerGroup][:publishables][:published] << layer_data
274
+ end
275
+
276
+ create_layergroup_uri = URI.join(GeoserverClient.api_root, "layergroups.json" )
277
+
278
+ # puts "Create layergroup uri = #{create_layergroup_uri}"
279
+
280
+ response = post_data(create_layergroup_uri, data.to_json, debug_mode)
281
+ response
282
+ end
283
+
284
+ def self.layergroups(debug_mode=false)
285
+ log "Geoserver::Get layergroups in workspace #{self.workspace}"
286
+
287
+ get_layergroups_uri = URI.join(GeoserverClient.api_root, "workspaces/#{GeoserverClient.workspace}/layergroups.json" )
288
+ get_data(get_layergroups_uri, {}, debug_mode )
289
+ end
290
+
291
+
292
+
293
+ def self.get_layergroup(layer_group_name, debug_mode = false)
294
+ log "Geoserver::Get layer-group #{layer_group_name} in datastore #{self.datastore}"
295
+
296
+ get_lg_uri = URI.join(GeoserverClient.api_root, "workspaces/#{GeoserverClient.workspace}/layergroups/#{layer_group_name}.json" )
297
+ get_data(get_lg_uri, {}, debug_mode )
298
+ end
299
+
300
+
301
+ def self.delete_layergroup(layer_group_name, debug_mode = false)
302
+ log "Geoserver::DELETE layer-group #{layer_group_name} in workspace #{self.workspace}"
303
+
304
+ get_lg_uri = URI.join(GeoserverClient.api_root, "workspaces/#{GeoserverClient.workspace}/layergroups/#{layer_group_name}.json" )
305
+ post_data(get_lg_uri, {}, debug_mode, method: :delete )
306
+ end
307
+
308
+
309
+ protected
310
+
311
+ def self.get_data(uri, data, debug_mode)
312
+ if debug_mode
313
+ log "URL = #{uri}"
314
+ @debugger = []
315
+ self.http_client.debug_dev = @debugger
316
+ end
317
+
318
+ auth = Base64.strict_encode64("#{GeoserverClient.api_user}:#{GeoserverClient.api_password}")
319
+ log "Authorization = #{auth}" if debug_mode
320
+
321
+ response = self.http_client.get(uri, data, {'Authorization' => "Basic #{auth}" })
322
+
323
+ log @debugger.inspect if debug_mode
324
+
325
+ raise StandardError.new(response.body) unless response.status == 200
326
+
327
+ JSON.parse(response.body) rescue response.body
328
+ end
329
+
330
+
331
+ def self.post_data(uri, data, debug_mode, options={})
332
+ http_method = options[:method] || :post
333
+ if debug_mode
334
+ log "URL = #{uri}"
335
+ @debugger = []
336
+ self.http_client.debug_dev = @debugger
337
+ end
338
+
339
+ auth = Base64.strict_encode64("#{GeoserverClient.api_user}:#{GeoserverClient.api_password}")
340
+ log "Authorization = #{auth}" if debug_mode
341
+
342
+ content_type = options[:content_type] || 'application/json'
343
+ # accept = options[:accept] || 'application/json'
344
+ accept = content_type
345
+
346
+ response = self.http_client.send(http_method, uri, data, {'Authorization' => "Basic #{auth}", 'Content-Type' => content_type, 'Accept' => accept } )
347
+
348
+ log @debugger.join.to_s if debug_mode
349
+
350
+ log "Response status = #{response.status}" if debug_mode
351
+
352
+
353
+ unless response.status == 200 || response.status == 201
354
+ if http_method == :delete && response.status == 404
355
+ log "Warning: did not exist or was already deleted. Error = #{response.body}"
356
+ else
357
+ log "Unexpected result: status = #{response.status}, body = #{response.body}"
358
+ log "DEBUGGER = #{@debugger.join.to_s}"
359
+ raise StandardError.new(response.body)
360
+ end
361
+ end
362
+ log response.inspect if debug_mode
363
+
364
+ response
365
+ end
366
+
367
+
368
+ end
369
+
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+ require 'geoserver_client'
3
+
4
+ describe GeoserverClient do
5
+
6
+ context "logger" do
7
+ context "if not set" do
8
+ it "returns nil" do
9
+ expect(GeoserverClient.logger).to eq(nil)
10
+ end
11
+ end
12
+ context "when set" do
13
+ before do
14
+ GeoserverClient.logger = :stdout
15
+ end
16
+ it "remembers the setting" do
17
+ expect(GeoserverClient.logger).to eq(:stdout)
18
+ end
19
+ end
20
+ end
21
+
22
+ [[:api_root, "", "http://localhost:8080/"], [:api_password, "geoserver", "other_password"], [:api_user, "admin", "other_user"]].each do |method|
23
+ describe "#{method[0]}" do
24
+ it "returns <#{method[1]}> by default" do
25
+ GeoserverClient.send("#{method[0]}=", nil)
26
+ expect(GeoserverClient.send(method[0])).to eq(method[1])
27
+ end
28
+ it "returns what is set before" do
29
+ GeoserverClient.send("#{method[0]}=", method[2])
30
+ expect(GeoserverClient.send(method[0])).to eq(method[2])
31
+ end
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,103 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # The `.rspec` file also contains a few flags that are not defaults but that
16
+ # users commonly want.
17
+ #
18
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
+ RSpec.configure do |config|
20
+ # rspec-expectations config goes here. You can use an alternate
21
+ # assertion/expectation library such as wrong or the stdlib/minitest
22
+ # assertions if you prefer.
23
+ config.expect_with :rspec do |expectations|
24
+ # This option will default to `true` in RSpec 4. It makes the `description`
25
+ # and `failure_message` of custom matchers include text for helper methods
26
+ # defined using `chain`, e.g.:
27
+ # be_bigger_than(2).and_smaller_than(4).description
28
+ # # => "be bigger than 2 and smaller than 4"
29
+ # ...rather than:
30
+ # # => "be bigger than 2"
31
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
32
+ end
33
+
34
+ # rspec-mocks config goes here. You can use an alternate test double
35
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
36
+ config.mock_with :rspec do |mocks|
37
+ # Prevents you from mocking or stubbing a method that does not exist on
38
+ # a real object. This is generally recommended, and will default to
39
+ # `true` in RSpec 4.
40
+ mocks.verify_partial_doubles = true
41
+ end
42
+
43
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
44
+ # have no way to turn it off -- the option exists only for backwards
45
+ # compatibility in RSpec 3). It causes shared context metadata to be
46
+ # inherited by the metadata hash of host groups and examples, rather than
47
+ # triggering implicit auto-inclusion in groups with matching metadata.
48
+ config.shared_context_metadata_behavior = :apply_to_host_groups
49
+
50
+ # The settings below are suggested to provide a good initial experience
51
+ # with RSpec, but feel free to customize to your heart's content.
52
+ =begin
53
+ # This allows you to limit a spec run to individual examples or groups
54
+ # you care about by tagging them with `:focus` metadata. When nothing
55
+ # is tagged with `:focus`, all examples get run. RSpec also provides
56
+ # aliases for `it`, `describe`, and `context` that include `:focus`
57
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
58
+ config.filter_run_when_matching :focus
59
+
60
+ # Allows RSpec to persist some state between runs in order to support
61
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
62
+ # you configure your source control system to ignore this file.
63
+ config.example_status_persistence_file_path = "spec/examples.txt"
64
+
65
+ # Limits the available syntax to the non-monkey patched syntax that is
66
+ # recommended. For more details, see:
67
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
68
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
69
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
70
+ config.disable_monkey_patching!
71
+
72
+ # This setting enables warnings. It's recommended, but in some cases may
73
+ # be too noisy due to issues in dependencies.
74
+ config.warnings = true
75
+
76
+ # Many RSpec users commonly either run the entire suite or an individual
77
+ # file, and it's useful to allow more verbose output when running an
78
+ # individual spec file.
79
+ if config.files_to_run.one?
80
+ # Use the documentation formatter for detailed output,
81
+ # unless a formatter has already been configured
82
+ # (e.g. via a command-line flag).
83
+ config.default_formatter = 'doc'
84
+ end
85
+
86
+ # Print the 10 slowest examples and example groups at the
87
+ # end of the spec run, to help surface which specs are running
88
+ # particularly slow.
89
+ config.profile_examples = 10
90
+
91
+ # Run specs in random order to surface order dependencies. If you find an
92
+ # order dependency and want to debug it, you can fix the order by providing
93
+ # the seed, which is printed after each run.
94
+ # --seed 1234
95
+ config.order = :random
96
+
97
+ # Seed global randomization in this process using the `--seed` CLI option.
98
+ # Setting this allows you to use `--seed` to deterministically reproduce
99
+ # test failures related to randomization by passing the same `--seed` value
100
+ # as the one that triggered the failure.
101
+ Kernel.srand config.seed
102
+ =end
103
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: geoserver_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Nathan Van der Auwera
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-05-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httpclient
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 3.5.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 3.5.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rdoc
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.12'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.12'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: juwelier
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 2.1.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 2.1.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Simple procedural client to consume the GeoServer REST API
98
+ email: "'nathan@dixis.com'"
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files:
102
+ - LICENSE.txt
103
+ - README.md
104
+ files:
105
+ - ".document"
106
+ - ".rspec"
107
+ - CODE_OF_CONDUCT.md
108
+ - Gemfile
109
+ - LICENSE.txt
110
+ - README.md
111
+ - Rakefile
112
+ - VERSION
113
+ - examples/rapl_zakbaken_s.png
114
+ - examples/test_geoserver_api.rb
115
+ - geoserver_client.gemspec
116
+ - lib/geoserver_client.rb
117
+ - spec/geoserver_client_spec.rb
118
+ - spec/spec_helper.rb
119
+ homepage: http://github.com/nathanvda/geoserver_client
120
+ licenses:
121
+ - MIT
122
+ metadata: {}
123
+ post_install_message:
124
+ rdoc_options: []
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ requirements: []
138
+ rubyforge_project:
139
+ rubygems_version: 2.6.11
140
+ signing_key:
141
+ specification_version: 4
142
+ summary: Simple GeoServer API client
143
+ test_files: []