acos_client 0.1.0.pre.alpha → 0.2.0.pre.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/Gemfile +0 -0
- data/Gemfile.lock +37 -0
- data/README.md +68 -4
- data/Rakefile +1 -1
- data/acos_client.gemspec +8 -11
- data/bin/a10_cli.rb +31 -0
- data/bin/console +3 -3
- data/lib/acos_client/application.rb +3 -0
- data/lib/acos_client/client.rb +2 -2
- data/lib/acos_client/errors.rb +0 -0
- data/lib/acos_client/tools.rb +1 -1
- data/lib/acos_client/v21/action.rb +0 -0
- data/lib/acos_client/v21/axapi_http.rb +3 -2
- data/lib/acos_client/v21/base.rb +1 -1
- data/lib/acos_client/v21/config_file.rb +0 -0
- data/lib/acos_client/v21/device_info.rb +3 -3
- data/lib/acos_client/v21/ha.rb +1 -1
- data/lib/acos_client/v21/log.rb +0 -0
- data/lib/acos_client/v21/monkey_patch_ssl.rb +2 -2
- data/lib/acos_client/v21/nat.rb +0 -0
- data/lib/acos_client/v21/network.rb +0 -0
- data/lib/acos_client/v21/partition.rb +0 -0
- data/lib/acos_client/v21/responses.rb +0 -0
- data/lib/acos_client/v21/session.rb +0 -0
- data/lib/acos_client/v21/slb/aflex.rb +51 -51
- data/lib/acos_client/v21/slb/class_list.rb +41 -41
- data/lib/acos_client/v21/slb/hm.rb +0 -0
- data/lib/acos_client/v21/slb/init.rb +0 -0
- data/lib/acos_client/v21/slb/member.rb +1 -1
- data/lib/acos_client/v21/slb/port.rb +0 -0
- data/lib/acos_client/v21/slb/server.rb +0 -0
- data/lib/acos_client/v21/slb/service_group.rb +1 -2
- data/lib/acos_client/v21/slb/template/init.rb +0 -0
- data/lib/acos_client/v21/slb/template/persistence.rb +53 -53
- data/lib/acos_client/v21/slb/template/template_ssl.rb +35 -35
- data/lib/acos_client/v21/slb/virtual_port.rb +73 -73
- data/lib/acos_client/v21/slb/virtual_server.rb +37 -37
- data/lib/acos_client/v21/slb/virtual_service.rb +39 -39
- data/lib/acos_client/v21/system.rb +0 -0
- data/lib/acos_client/version.rb +1 -1
- data/lib/acos_client.rb +0 -0
- metadata +11 -9
- data/.travis.yml +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4359d520bfa3c4d522a54846e38bd5b564d4f9a6
|
4
|
+
data.tar.gz: 3762c6f41a72301a3b96a189756185cdb4dfc93f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8bd32393590a755f99ab79cae305e5a7908ab206377f170087679395450c047098e0c74758398b65f6103a5dadf3d5ed6f8d95e0f27bbb0ed484be297038b288
|
7
|
+
data.tar.gz: 60cbae9fe6e893e6951f76468b02812b43b1a0029c68ced52b3a04d7b8bbd90eaa717e7fac4e94ed6415d3d1d08de2735ce8b845225958f78a3018ca2ff06fea
|
data/.gitignore
ADDED
data/Gemfile
CHANGED
File without changes
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
acos_client (0.2.0.pre.alpha)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
activesupport (4.2.3)
|
10
|
+
i18n (~> 0.7)
|
11
|
+
json (~> 1.7, >= 1.7.7)
|
12
|
+
minitest (~> 5.1)
|
13
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
14
|
+
tzinfo (~> 1.1)
|
15
|
+
addressable (2.3.8)
|
16
|
+
httparty (0.13.5)
|
17
|
+
json (~> 1.8)
|
18
|
+
multi_xml (>= 0.5.2)
|
19
|
+
i18n (0.7.0)
|
20
|
+
json (1.8.3)
|
21
|
+
minitest (5.7.0)
|
22
|
+
multi_xml (0.5.5)
|
23
|
+
rake (0.9.6)
|
24
|
+
thread_safe (0.3.5)
|
25
|
+
tzinfo (1.2.2)
|
26
|
+
thread_safe (~> 0.1)
|
27
|
+
|
28
|
+
PLATFORMS
|
29
|
+
ruby
|
30
|
+
|
31
|
+
DEPENDENCIES
|
32
|
+
acos_client!
|
33
|
+
activesupport
|
34
|
+
addressable
|
35
|
+
bundler (~> 1.7)
|
36
|
+
httparty
|
37
|
+
rake (~> 0.9.6)
|
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# AcosClient
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/acos_client.svg)](http://badge.fury.io/rb/acos_client)
|
2
3
|
|
3
|
-
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/acos_client`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
-
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
6
4
|
|
7
5
|
## Installation
|
8
6
|
|
@@ -22,7 +20,73 @@ Or install it yourself as:
|
|
22
20
|
|
23
21
|
## Usage
|
24
22
|
|
25
|
-
|
23
|
+
### Connect
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
require 'acos_client'
|
27
|
+
|
28
|
+
c = AcosClient::Client.new('admin', 'a10', '192.168.1.10')
|
29
|
+
c.session.id
|
30
|
+
#=> a83d5780ee403f43ff83e46be7a9ff
|
31
|
+
c.session.close
|
32
|
+
#=> {:response=>{:status=>"OK"}}
|
33
|
+
```
|
34
|
+
|
35
|
+
### Servers
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
servers = [{
|
39
|
+
:name => 'server1.mydns.com',
|
40
|
+
:host => '172.16.0.1',
|
41
|
+
:port => '80'
|
42
|
+
}, {
|
43
|
+
:name => 'server2.mydns.com',
|
44
|
+
:host => '172.16.0.2',
|
45
|
+
:port => '80'
|
46
|
+
}]
|
47
|
+
|
48
|
+
servers.each do |server|
|
49
|
+
puts "Create: #{server}"
|
50
|
+
c.slb.server.create(server[:name], server[:host])
|
51
|
+
c.slb.server.port.create(server[:name], server[:port], AcosClient::V21::Port::TCP)
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
### Service Group
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
c.slb.service_group.create('pool1',
|
59
|
+
protocol: AcosClient::V21::ServiceGroup::TCP,
|
60
|
+
lb_method: AcosClient::V21::ServiceGroup::ROUND_ROBIN)
|
61
|
+
|
62
|
+
# Add Members
|
63
|
+
c.slb.service_group.member.create('pool1', 'server1.mydns.com', '80')
|
64
|
+
c.slb.service_group.member.create('pool1', 'server2.mydns.com', '80')
|
65
|
+
```
|
66
|
+
|
67
|
+
### Virtual Server
|
68
|
+
```ruby
|
69
|
+
c.slb.virtual_server.create('vip1', '172.16.0.10')
|
70
|
+
```
|
71
|
+
|
72
|
+
#### Health Monitor
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
c.slb.hm.create('hm1', AcosClient::V21::HealthMonitor::HTTP, 5, 5, 5,
|
76
|
+
method: 'GET',
|
77
|
+
url: '/',
|
78
|
+
expect_code: '200',
|
79
|
+
port: 80 )
|
80
|
+
|
81
|
+
# Update Service Group with HM
|
82
|
+
c.slb.service_group.update('pool1', health_monitor: 'hm1')
|
83
|
+
```
|
84
|
+
|
85
|
+
### Virtual Service
|
86
|
+
```ruby
|
87
|
+
c.slb.virtual_service.create('vs1', 14, 80, '172.16.0.10', 'pool1')
|
88
|
+
|
89
|
+
```
|
26
90
|
|
27
91
|
## Development
|
28
92
|
|
data/Rakefile
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
data/acos_client.gemspec
CHANGED
@@ -4,26 +4,23 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'acos_client/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'acos_client'
|
8
8
|
spec.version = AcosClient::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
9
|
+
spec.authors = ['Amine Benseddik']
|
10
|
+
spec.email = ['amine.benseddik@gmail.com']
|
11
11
|
|
12
12
|
spec.summary = %q{A10network AxAPI client}
|
13
13
|
spec.description = %q{Port Python A10network AxAPI client to Ruby}
|
14
|
-
spec.homepage =
|
14
|
+
spec.homepage = 'https://github.com/amine7536/acos_client'
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
-
spec.bindir =
|
17
|
+
spec.bindir = 'exe'
|
18
18
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
-
spec.require_paths = [
|
19
|
+
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.
|
22
|
-
|
23
|
-
spec.add_development_dependency "bundler", "~> 1.9"
|
24
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
22
|
+
spec.add_development_dependency 'rake', '~> 0.9.6'
|
25
23
|
spec.add_development_dependency 'httparty'
|
26
24
|
spec.add_development_dependency 'addressable'
|
27
25
|
spec.add_development_dependency 'activesupport'
|
28
|
-
|
29
26
|
end
|
data/bin/a10_cli.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# For security reasons, ensure that '.' is not on the load path
|
4
|
+
# This is primarily for 1.8.7 since 1.9.2+ doesn't put '.' on the load path
|
5
|
+
$LOAD_PATH.delete '.'
|
6
|
+
|
7
|
+
# Bundler and rubygems maintain a set of directories from which to
|
8
|
+
# load gems. If Bundler is loaded, let it determine what can be
|
9
|
+
# loaded. If it's not loaded, then use rubygems. But do this before
|
10
|
+
# loading any facter code, so that our gem loading system is sane.
|
11
|
+
if not defined? ::Bundler
|
12
|
+
begin
|
13
|
+
require 'rubygems'
|
14
|
+
rescue LoadError
|
15
|
+
#pass
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'acos_client'
|
20
|
+
|
21
|
+
begin
|
22
|
+
AcosClient::Application.run(ARGV)
|
23
|
+
|
24
|
+
rescue Errno::ENOENT => err
|
25
|
+
|
26
|
+
abort "AcosClient: #{err.message}"
|
27
|
+
|
28
|
+
rescue OptionParser::InvalidOption => err
|
29
|
+
|
30
|
+
abort "AcosClient: #{err.message}"
|
31
|
+
end
|
data/bin/console
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'acos_client'
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +10,5 @@ require "acos_client"
|
|
10
10
|
# require "pry"
|
11
11
|
# Pry.start
|
12
12
|
|
13
|
-
require
|
13
|
+
require 'irb'
|
14
14
|
IRB.start
|
data/lib/acos_client/client.rb
CHANGED
@@ -24,7 +24,7 @@ module AcosClient
|
|
24
24
|
|
25
25
|
attr_accessor :http, :session, :system, :current_partition
|
26
26
|
|
27
|
-
def initialize(username, password, host, protocol:
|
27
|
+
def initialize(username, password, host, protocol: 'https', port: nil)
|
28
28
|
|
29
29
|
@http = AcosClient::V21::HttpClient.new(host, protocol: protocol, port: port)
|
30
30
|
@session = AcosClient::V21::Session.new(self, username, password)
|
@@ -55,4 +55,4 @@ module AcosClient
|
|
55
55
|
|
56
56
|
end
|
57
57
|
|
58
|
-
end
|
58
|
+
end
|
data/lib/acos_client/errors.rb
CHANGED
File without changes
|
data/lib/acos_client/tools.rb
CHANGED
File without changes
|
@@ -43,8 +43,8 @@ module AcosClient
|
|
43
43
|
default_options.update(verify: false)
|
44
44
|
|
45
45
|
HEADERS = {
|
46
|
-
|
47
|
-
|
46
|
+
'Content-type' => 'application/json',
|
47
|
+
'User-Agent' => "ACOS-Ruby-Client-AGENT-#{VERSION}",
|
48
48
|
}
|
49
49
|
|
50
50
|
attr_accessor :host, :port, :protocol
|
@@ -72,6 +72,7 @@ module AcosClient
|
|
72
72
|
# Todo: Catch http/httparty exceptions
|
73
73
|
#
|
74
74
|
|
75
|
+
params_copy = {}
|
75
76
|
if !params.empty?
|
76
77
|
params_copy = params.merge(opts)
|
77
78
|
end
|
data/lib/acos_client/v21/base.rb
CHANGED
File without changes
|
@@ -6,15 +6,15 @@ module AcosClient
|
|
6
6
|
class DeviceInfo < AcosClient::V21::BaseV21
|
7
7
|
|
8
8
|
def get(**opts)
|
9
|
-
|
9
|
+
self._get('system.device_info.get', **opts)
|
10
10
|
end
|
11
11
|
|
12
12
|
def cpu_current_usage(**opts)
|
13
|
-
|
13
|
+
self._get('system.device_info.cpu.current_usage.get', **opts)
|
14
14
|
end
|
15
15
|
|
16
16
|
def cpu_historical_usage(**opts)
|
17
|
-
|
17
|
+
self._get('system.device_info.cpu.historical_usage.get', *opts)
|
18
18
|
end
|
19
19
|
|
20
20
|
end
|
data/lib/acos_client/v21/ha.rb
CHANGED
data/lib/acos_client/v21/log.rb
CHANGED
File without changes
|
@@ -3,11 +3,11 @@ module OpenSSL
|
|
3
3
|
class SSLContext
|
4
4
|
remove_const(:DEFAULT_PARAMS)
|
5
5
|
DEFAULT_PARAMS = {
|
6
|
-
:ssl_version =>
|
6
|
+
:ssl_version => 'TLSv1',
|
7
7
|
:verify_mode => OpenSSL::SSL::VERIFY_PEER,
|
8
8
|
:ciphers => %w{
|
9
9
|
DES-CBC3-SHA
|
10
|
-
}.join(
|
10
|
+
}.join(':'),
|
11
11
|
:options => -> {
|
12
12
|
opts = OpenSSL::SSL::OP_ALL
|
13
13
|
opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS)
|
data/lib/acos_client/v21/nat.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -6,84 +6,84 @@ module AcosClient
|
|
6
6
|
#
|
7
7
|
# Todo: implement multipart upload
|
8
8
|
#
|
9
|
-
|
9
|
+
class Aflex < AcosClient::V21::BaseV21
|
10
10
|
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
def _set(action, name, aflex, **opts)
|
13
|
+
# m = multipart.Multipart
|
14
|
+
# m.file(name="upload_aflex", filename=name, value=aflex)
|
15
|
+
# ct, payload = m.get
|
16
|
+
# kwargs.update(payload=payload, headers={'Content-Type': ct})
|
17
|
+
# self._post(action, **opts)
|
18
|
+
end
|
19
19
|
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
def upload(name, aflex, **opts)
|
22
|
+
self._set('slb.aflex.upload', name, aflex, **opts)
|
23
|
+
end
|
24
24
|
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
def update(name, aflex, **opts)
|
27
|
+
self._set('slb.aflex.update', name, aflex, **opts)
|
28
|
+
end
|
29
29
|
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
def all(**opts)
|
32
|
+
self._get('slb.aflex.getAll')
|
33
|
+
end
|
34
34
|
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
def get(name, **opts)
|
37
|
+
self._post('slb.aflex.search', params: {:name => name}, **opts)
|
38
|
+
end
|
39
39
|
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
def download(name, **opts)
|
42
|
+
self._post('slb.aflex.download', params: {:name => name}, **opts)
|
43
|
+
end
|
44
44
|
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
def delete(name, **opts)
|
47
|
+
self._post('slb.aflex.delete', params: {:name => name}, **opts)
|
48
|
+
end
|
49
49
|
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
def stats(name, **opts)
|
52
|
+
self._post('slb.aflex.fetchStatistics', params: {:name => name}, **opts)
|
53
|
+
end
|
54
54
|
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
def all_stats(**opts)
|
57
|
+
self._get('slb.aflex.fetchAllstatistics', **opts)
|
58
|
+
end
|
59
59
|
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
def clear_stats(name, **opts)
|
62
|
+
self._post('slb.aflex.slb.aflex.clearStatistics', params: {:name => name}, **opts)
|
63
|
+
end
|
64
64
|
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
|
66
|
+
def clear_all_stats(**opts)
|
67
|
+
self._post('slb.aflex.clearAllStatistics', **opts)
|
68
|
+
end
|
69
69
|
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
}
|
71
|
+
def clear_events(name, event_name, **opts)
|
72
|
+
params = {
|
73
|
+
:aflex_event => {
|
74
|
+
:name => name,
|
75
|
+
:event_name => event_name
|
77
76
|
}
|
78
|
-
|
79
|
-
|
77
|
+
}
|
78
|
+
self._post('slb.aflex.clearEvents', params: params, **opts)
|
79
|
+
end
|
80
80
|
|
81
81
|
|
82
|
-
|
83
|
-
|
84
|
-
|
82
|
+
def clear_all_events(**opts)
|
83
|
+
self._post('slb.aflax.clearAllEvents', **opts)
|
84
|
+
end
|
85
85
|
|
86
|
-
|
86
|
+
end
|
87
87
|
|
88
|
-
|
88
|
+
end
|
89
89
|
end
|
@@ -10,58 +10,58 @@ module AcosClient
|
|
10
10
|
# ToDo: implement multipart upload
|
11
11
|
#
|
12
12
|
|
13
|
-
|
13
|
+
class ClassList < AcosClient::V21::BaseV21
|
14
14
|
|
15
|
-
|
15
|
+
IPV4 = 2
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
def _fix_json(data)
|
18
|
+
# p = re.compile(r '(?<=[^:{\[,])"(?![:,}\]])')
|
19
|
+
# json.loads(re.sub(p, '\\"', data))
|
20
|
+
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
def all(**opts)
|
23
|
+
#self._fix_json(self._get('slb.class_list.getAll', **opts))
|
24
|
+
self._get('slb.class_list.getAll', **opts)
|
25
|
+
end
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
def get(name, **opts)
|
28
|
+
self._fix_json(self._post('slb.class_list.search', params: {:name => name}, **opts))
|
29
|
+
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
def download(name, **opts)
|
32
|
+
self._post('slb.class_list.download', params: {:file_name => name}, **opts)
|
33
|
+
end
|
34
34
|
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
def upload(name, class_list, **opts)
|
37
|
+
#m = multipart.Multipart()
|
38
|
+
#m.file(name=name, filename=name, value=class_list)
|
39
|
+
#ct, payload = m.get()
|
40
|
+
#kwargs.update(payload=payload, headers={'Content-Type' : ct})
|
41
|
+
# self._post('slb.class_list.upload', **opts)
|
42
|
+
end
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
def _set(action, class_list, **opts)
|
45
|
+
self._post(action, params: {:name => class_list}, **opts)
|
46
|
+
end
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
48
|
+
def create(class_list, type=IPV4, **opts)
|
49
|
+
params = {
|
50
|
+
:name => class_list,
|
51
|
+
:type => type
|
52
|
+
}
|
53
|
+
self._post('slb.class_list.create', params: params, **opts)
|
54
|
+
end
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
def update(class_list, **opts)
|
57
|
+
self._set('slb.class_list.update', class_list, **opts)
|
58
|
+
end
|
59
59
|
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
def delete(name, **opts)
|
61
|
+
self._post('slb.class_list.delete', params: {:name => name}, **opts)
|
62
|
+
end
|
63
63
|
|
64
|
-
|
64
|
+
end
|
65
65
|
|
66
|
-
|
66
|
+
end
|
67
67
|
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|