concourse-objects 1.32.1 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/concourse-objects.rb +2 -1
- data/lib/concourse-objects/resources.rb +53 -0
- data/lib/concourse-objects/resources/alertmanager.rb +58 -0
- data/lib/concourse-objects/resources/android-sdk.rb +27 -0
- data/lib/concourse-objects/resources/ansible-playbook.rb +68 -0
- data/lib/concourse-objects/resources/artifactory-deb.rb +54 -0
- data/lib/concourse-objects/resources/artifactory.rb +33 -0
- data/lib/concourse-objects/resources/bender.rb +61 -0
- data/lib/concourse-objects/resources/bosh-io-release.rb +1 -0
- data/lib/concourse-objects/resources/bosh-io-stemcell.rb +1 -0
- data/lib/concourse-objects/resources/bosh-release.rb +64 -0
- data/lib/concourse-objects/resources/calendar.rb +36 -0
- data/lib/concourse-objects/resources/cf-event.rb +38 -0
- data/lib/concourse-objects/resources/cf-flyway.rb +45 -0
- data/lib/concourse-objects/resources/cf-zero-downtime.rb +64 -0
- data/lib/concourse-objects/resources/cf.rb +1 -0
- data/lib/concourse-objects/resources/chartmuseum.rb +56 -0
- data/lib/concourse-objects/resources/concourse-pipeline.rb +1 -0
- data/lib/concourse-objects/resources/deploygate.rb +38 -0
- data/lib/concourse-objects/resources/devpi.rb +44 -0
- data/lib/concourse-objects/resources/docker-compose.rb +131 -0
- data/lib/concourse-objects/resources/docker-image.rb +1 -0
- data/lib/concourse-objects/resources/email.rb +1 -0
- data/lib/concourse-objects/resources/fly.rb +46 -0
- data/lib/concourse-objects/resources/gcs.rb +61 -0
- data/lib/concourse-objects/resources/gerrit.rb +49 -0
- data/lib/concourse-objects/resources/git.rb +1 -0
- data/lib/concourse-objects/resources/github-list-repos.rb +1 -0
- data/lib/concourse-objects/resources/github-pr.rb +1 -0
- data/lib/concourse-objects/resources/github-release.rb +1 -0
- data/lib/concourse-objects/resources/github-status.rb +48 -0
- data/lib/concourse-objects/resources/github-webhook.rb +1 -0
- data/lib/concourse-objects/resources/grafana.rb +1 -0
- data/lib/concourse-objects/resources/hangouts.rb +35 -0
- data/lib/concourse-objects/resources/helm-chart.rb +1 -0
- data/lib/concourse-objects/resources/helm.rb +1 -0
- data/lib/concourse-objects/resources/hg.rb +1 -0
- data/lib/concourse-objects/resources/hipchat-notification.rb +1 -0
- data/lib/concourse-objects/resources/hockey.rb +32 -0
- data/lib/concourse-objects/resources/irc-notification.rb +1 -0
- data/lib/concourse-objects/resources/keyval.rb +1 -0
- data/lib/concourse-objects/resources/kubernetes-resource.rb +41 -0
- data/lib/concourse-objects/resources/kubernetes.rb +55 -0
- data/lib/concourse-objects/resources/marathon.rb +45 -0
- data/lib/concourse-objects/resources/maven.rb +43 -0
- data/lib/concourse-objects/resources/metadata.rb +1 -0
- data/lib/concourse-objects/resources/mock.rb +1 -0
- data/lib/concourse-objects/resources/newrelic-deploy.rb +31 -0
- data/lib/concourse-objects/resources/pool.rb +1 -0
- data/lib/concourse-objects/resources/registry-image.rb +1 -0
- data/lib/concourse-objects/resources/repo.rb +31 -0
- data/lib/concourse-objects/resources/rocketchat-notification.rb +43 -0
- data/lib/concourse-objects/resources/romver.rb +81 -0
- data/lib/concourse-objects/resources/rss.rb +1 -0
- data/lib/concourse-objects/resources/rubygems.rb +1 -0
- data/lib/concourse-objects/resources/s3.rb +1 -0
- data/lib/concourse-objects/resources/semver.rb +1 -0
- data/lib/concourse-objects/resources/serverspec.rb +30 -0
- data/lib/concourse-objects/resources/slack-notification.rb +1 -0
- data/lib/concourse-objects/resources/sonarqube.rb +70 -0
- data/lib/concourse-objects/resources/swift.rb +43 -0
- data/lib/concourse-objects/resources/telegram.rb +41 -0
- data/lib/concourse-objects/resources/time.rb +1 -0
- metadata +35 -2
- metadata.gz.sig +2 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5328875ddb2c5fc34456355073895b41f5e03891b31a784bfb115c88c24f9a79
|
4
|
+
data.tar.gz: 4c885cc54ea083ba9fe5c6a148cb21dc10816e7d10a8b9b1f82411613fb9f08c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 735d7a3ab96c4e877763c1eda8ce737a03930da5acac44a69e1034a9fd985878f4f0128d4ab3c578fc865a020bd4ed60c4a83c388ae84751b7e7904e3c8ed5c2
|
7
|
+
data.tar.gz: 1cb3cbc65fd42aaf1608dabc97925e10b1328a6cfae2b86a7bb345aa578ba80f107981a682b6abd680f90dad405de60ca31c04e0d960f765b9f57cbc3cee1387
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/lib/concourse-objects.rb
CHANGED
@@ -13,22 +13,55 @@ require_relative "resources/s3"
|
|
13
13
|
require_relative "resources/semver"
|
14
14
|
require_relative "resources/time"
|
15
15
|
|
16
|
+
require_relative "resources/alertmanager"
|
17
|
+
require_relative "resources/android-sdk"
|
18
|
+
require_relative "resources/ansible-playbook"
|
19
|
+
require_relative "resources/artifactory"
|
20
|
+
require_relative "resources/artifactory-deb"
|
21
|
+
require_relative "resources/bender"
|
22
|
+
require_relative "resources/bosh-release"
|
23
|
+
require_relative "resources/calendar"
|
24
|
+
require_relative "resources/cf-event"
|
25
|
+
require_relative "resources/cf-flyway"
|
26
|
+
require_relative "resources/cf-zero-downtime"
|
27
|
+
require_relative "resources/chartmuseum"
|
16
28
|
require_relative "resources/concourse-pipeline"
|
29
|
+
require_relative "resources/deploygate"
|
30
|
+
require_relative "resources/devpi"
|
31
|
+
require_relative "resources/docker-compose"
|
17
32
|
require_relative "resources/email"
|
33
|
+
require_relative "resources/fly"
|
34
|
+
require_relative "resources/gcs"
|
35
|
+
require_relative "resources/gerrit"
|
18
36
|
require_relative "resources/github-list-repos"
|
19
37
|
require_relative "resources/github-pr"
|
38
|
+
require_relative "resources/github-status"
|
20
39
|
require_relative "resources/github-webhook"
|
21
40
|
require_relative "resources/grafana"
|
41
|
+
require_relative "resources/hangouts"
|
22
42
|
require_relative "resources/helm"
|
23
43
|
require_relative "resources/helm-chart"
|
24
44
|
require_relative "resources/hipchat-notification"
|
45
|
+
require_relative "resources/hockey"
|
25
46
|
require_relative "resources/irc-notification"
|
26
47
|
require_relative "resources/keyval"
|
48
|
+
require_relative "resources/kubernetes"
|
49
|
+
require_relative "resources/kubernetes-resource"
|
50
|
+
require_relative "resources/marathon"
|
51
|
+
require_relative "resources/maven"
|
27
52
|
require_relative "resources/metadata"
|
28
53
|
require_relative "resources/mock"
|
54
|
+
require_relative "resources/newrelic-deploy"
|
55
|
+
require_relative "resources/repo"
|
56
|
+
require_relative "resources/rocketchat-notification"
|
57
|
+
require_relative "resources/romver"
|
29
58
|
require_relative "resources/rss"
|
30
59
|
require_relative "resources/rubygems"
|
60
|
+
require_relative "resources/serverspec"
|
31
61
|
require_relative "resources/slack-notification"
|
62
|
+
require_relative "resources/sonarqube"
|
63
|
+
require_relative "resources/swift"
|
64
|
+
require_relative "resources/telegram"
|
32
65
|
|
33
66
|
module ConcourseObjects
|
34
67
|
module Resources
|
@@ -50,6 +83,12 @@ module ConcourseObjects
|
|
50
83
|
end
|
51
84
|
end
|
52
85
|
|
86
|
+
def self.licensed_resources
|
87
|
+
resources.select do |resource|
|
88
|
+
resource.const_defined?(:RESOURCE_LICENSE)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
53
92
|
def self.find(name)
|
54
93
|
named_resources.find do |resource|
|
55
94
|
name === resource.const_get(:RESOURCE_NAME)
|
@@ -62,6 +101,20 @@ module ConcourseObjects
|
|
62
101
|
end
|
63
102
|
end
|
64
103
|
|
104
|
+
def self.licensed(license)
|
105
|
+
licensed_resources.select do |resource|
|
106
|
+
license === resource.const_get(:RESOURCE_LICENSE)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.licenses
|
111
|
+
resources.group_by do |resource|
|
112
|
+
resource.const_get(:RESOURCE_LICENSE) if resource.const_defined?(:RESOURCE_LICENSE)
|
113
|
+
end.sort_by do |key, value|
|
114
|
+
value.count
|
115
|
+
end.reverse.to_h
|
116
|
+
end
|
117
|
+
|
65
118
|
def self.owners
|
66
119
|
resources.group_by do |resource|
|
67
120
|
resource.const_get(:GITHUB_OWNER) if resource.const_defined?(:GITHUB_OWNER)
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../concourse-objects"
|
4
|
+
|
5
|
+
module ConcourseObjects
|
6
|
+
module Resources
|
7
|
+
class AlertManager < Resource
|
8
|
+
RESOURCE_NAME = "alertmanager"
|
9
|
+
RESOURCE_LICENSE = "Apache-2.0"
|
10
|
+
GITHUB_OWNER = "frodenas"
|
11
|
+
GITHUB_REPOSITORY = "frodenas/alertmanager-resource"
|
12
|
+
GITHUB_VERSION = "v0.3.0"
|
13
|
+
|
14
|
+
class Source < Object
|
15
|
+
required :url, write: AsString
|
16
|
+
end
|
17
|
+
|
18
|
+
class OutParams < Object
|
19
|
+
class Silence < Object
|
20
|
+
DEFAULT_EXPIRES = "1h"
|
21
|
+
|
22
|
+
required :matchers, write: AsString
|
23
|
+
|
24
|
+
optional :creator, write: AsString
|
25
|
+
optional :comments, write: AsString
|
26
|
+
optional :expires, write: AsString, default: proc { DEFAULT_EXPIRES }
|
27
|
+
|
28
|
+
def initialize(options = {})
|
29
|
+
super(options.merge(operation: "silence")) do |this, options|
|
30
|
+
yield this, options if block_given?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Expire < Object
|
36
|
+
required :silence, write: AsString
|
37
|
+
|
38
|
+
def initialize(options = {})
|
39
|
+
super(options.merge(operation: "expire")) do |this, options|
|
40
|
+
yield this, options if block_given?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
ACCEPTABLE_OPERATIONS = ["silence", "expire"]
|
46
|
+
OperationIsAcceptable = proc { |_, operation| ACCEPTABLE_OPERATIONS.include?(operation) }
|
47
|
+
|
48
|
+
required :operation, write: AsString, guard: OperationIsAcceptable
|
49
|
+
end
|
50
|
+
|
51
|
+
optional :source, write: Source
|
52
|
+
|
53
|
+
def initialize(options = {})
|
54
|
+
super(options.merge(type: "alertmanager"))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../concourse-objects"
|
4
|
+
|
5
|
+
module ConcourseObjects
|
6
|
+
module Resources
|
7
|
+
class AndroidSDK < Resource
|
8
|
+
RESOURCE_NAME = "android-sdk"
|
9
|
+
RESOURCE_LICENSE = "MIT"
|
10
|
+
GITHUB_OWNER = "xaethos"
|
11
|
+
GITHUB_REPOSITORY = "xaethos/android-sdk-resource"
|
12
|
+
GITHUB_VERSION = "v0.2"
|
13
|
+
|
14
|
+
class Source < Object
|
15
|
+
DEFAULT_COMPONENTS = ["platform-tools"]
|
16
|
+
|
17
|
+
required :components, write: AsArrayOf.(:to_s), default: proc { DEFAULT_COMPONENTS }
|
18
|
+
end
|
19
|
+
|
20
|
+
optional :source, write: Source
|
21
|
+
|
22
|
+
def initialize(options = {})
|
23
|
+
super(options.merge(type: "android-sdk"))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../concourse-objects"
|
4
|
+
|
5
|
+
module ConcourseObjects
|
6
|
+
module Resources
|
7
|
+
class AnsiblePlaybook < Resource
|
8
|
+
RESOURCE_NAME = "ansible-playbook"
|
9
|
+
RESOURCE_LICENSE = "MIT"
|
10
|
+
GITHUB_OWNER = "troykinsella"
|
11
|
+
GITHUB_REPOSITORY = "troykinsella/concourse-ansible-playbook-resource"
|
12
|
+
GITHUB_VERSION = "1.0.0"
|
13
|
+
|
14
|
+
class Source < Object
|
15
|
+
DEFAULT_DEBUG = false
|
16
|
+
DEFAULT_GIT_SKIP_SSL_VERIFICATION = false
|
17
|
+
DEFAULT_REQUIREMENTS = "requirements.yml"
|
18
|
+
|
19
|
+
required :ssh_private_key
|
20
|
+
|
21
|
+
optional :env, write: AsHashOf.(:to_s, :to_s), default: EmptyHash
|
22
|
+
optional :git_global_config, write: AsHash, default: EmptyHash
|
23
|
+
optional :debug, write: AsBoolean, default: proc { DEFAULT_DEBUG }
|
24
|
+
optional :git_skip_ssl_verification, write: AsBoolean, default: proc { DEFAULT_GIT_SKIP_SSL_VERIFICATION }
|
25
|
+
optional :requirements, write: AsString, default: proc { DEFAULT_REQUIREMENTS }
|
26
|
+
optional :git_https_username, write: AsString
|
27
|
+
optional :git_https_password, write: AsString
|
28
|
+
optional :git_private_key, write: AsString
|
29
|
+
optional :user, write: AsString
|
30
|
+
optional :ssh_common_args, write: AsString
|
31
|
+
optional :vault_password, write: AsString
|
32
|
+
optional :verbose, write: AsString
|
33
|
+
end
|
34
|
+
|
35
|
+
class OutParams < Object
|
36
|
+
DEFAULT_BECOME = false
|
37
|
+
DEFAULT_CHECK = false
|
38
|
+
DEFAULT_DIFF = false
|
39
|
+
DEFAULT_PLAYBOOK = "site.yml"
|
40
|
+
|
41
|
+
required :inventory, write: AsString
|
42
|
+
required :path, write: AsString
|
43
|
+
|
44
|
+
optional :vars, write: AsHash, default: EmptyHash
|
45
|
+
optional :diff, write: AsBoolean, default: proc { DEFAULT_DIFF }
|
46
|
+
optional :become, write: AsBoolean, default: proc { DEFAULT_BECOME }
|
47
|
+
optional :playbook, write: AsString, default: proc { DEFAULT_PLAYBOOK }
|
48
|
+
optional :become_user, write: AsString
|
49
|
+
optional :become_method, write: AsString
|
50
|
+
optional :vars_file, write: AsString
|
51
|
+
|
52
|
+
def initialize(options = {})
|
53
|
+
super(options) do |this, options|
|
54
|
+
raise KeyError, "#{self.class.inspect} requires one of (vars, vars_file), not both" if (this.vars? and this.vars_file?)
|
55
|
+
|
56
|
+
yield this, options if block_given?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
optional :source, write: Source
|
62
|
+
|
63
|
+
def initialize(options = {})
|
64
|
+
super(options.merge(type: "ansible-playbook"))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../concourse-objects"
|
4
|
+
|
5
|
+
module ConcourseObjects
|
6
|
+
module Resources
|
7
|
+
class ArtifactoryDeb < Resource
|
8
|
+
RESOURCE_NAME = "artifactory-deb"
|
9
|
+
RESOURCE_LICENSE = "MIT"
|
10
|
+
GITHUB_OWNER = "troykinsella"
|
11
|
+
GITHUB_REPOSITORY = "troykinsella/concourse-artifactory-deb-resource"
|
12
|
+
GITHUB_VERSION = "1.0.0"
|
13
|
+
|
14
|
+
class Source < Object
|
15
|
+
DEFAULT_ARCHITECTURE = "amd64"
|
16
|
+
DEFAULT_COMPONENT = "main"
|
17
|
+
DEFAULT_COMPONENTS_DIR = "pool"
|
18
|
+
DEFAULT_TRUSTED = false
|
19
|
+
|
20
|
+
required :distribution, write: AsString
|
21
|
+
required :package, write: AsString
|
22
|
+
required :password, write: AsString
|
23
|
+
required :repostory, write: AsString
|
24
|
+
required :username, write: AsString
|
25
|
+
|
26
|
+
optional :apt_keys, write: AsArrayOf.(:to_s), default: EmptyArray
|
27
|
+
optional :other_sources, write: AsArrayOf.(:to_s), default: EmptyArray
|
28
|
+
optional :trusted, write: AsBoolean, default: proc { DEFAULT_TRUSTED }
|
29
|
+
optional :architecture, write: AsString, default: proc { DEFAULT_ARCHITECTURE }
|
30
|
+
optional :component, write: AsString, default: proc { DEFAULT_COMPONENT }
|
31
|
+
optional :components_dir, write: AsString, default: proc { DEFAULT_COMPONENTS_DIR }
|
32
|
+
optional :version_pattern, write: AsString
|
33
|
+
end
|
34
|
+
|
35
|
+
class InParams < Object
|
36
|
+
DEFAULT_FETCH_ARCHIVES = false
|
37
|
+
|
38
|
+
optional :fetch_archives, write: AsBoolean, default: proc { DEFAULT_FETCH_ARCHIVES }
|
39
|
+
end
|
40
|
+
|
41
|
+
class OutParams < Object
|
42
|
+
required :debs, write: AsString
|
43
|
+
|
44
|
+
optional :deb_pattern, write: AsString
|
45
|
+
end
|
46
|
+
|
47
|
+
optional :source, write: Source
|
48
|
+
|
49
|
+
def initialize(options = {})
|
50
|
+
super(options.merge(type: "artifactory-deb"))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../concourse-objects"
|
4
|
+
|
5
|
+
module ConcourseObjects
|
6
|
+
module Resources
|
7
|
+
class Artifactory < Resource
|
8
|
+
RESOURCE_NAME = "artifactory"
|
9
|
+
RESOURCE_LICENSE = "MIT"
|
10
|
+
GITHUB_OWNER = "troykinsella"
|
11
|
+
GITHUB_REPOSITORY = "troykinsella/concourse-artifactory-resource"
|
12
|
+
GITHUB_VERSION = "1.0.0"
|
13
|
+
|
14
|
+
class Source < Object
|
15
|
+
required :repository, write: AsString
|
16
|
+
required :api_key, write: AsString
|
17
|
+
|
18
|
+
optional :path, write: AsString
|
19
|
+
end
|
20
|
+
|
21
|
+
class OutParams < Object
|
22
|
+
optional :files, write: AsString
|
23
|
+
optional :flob, write: AsString
|
24
|
+
end
|
25
|
+
|
26
|
+
optional :source, write: Source
|
27
|
+
|
28
|
+
def initialize(options = {})
|
29
|
+
super(options.merge(type: "artifactory"))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../concourse-objects"
|
4
|
+
|
5
|
+
module ConcourseObjects
|
6
|
+
module Resources
|
7
|
+
class Bender < Resource
|
8
|
+
RESOURCE_NAME = "bender"
|
9
|
+
RESOURCE_LICENSE = "MIT"
|
10
|
+
GITHUB_OWNER = "ahelal"
|
11
|
+
GITHUB_REPOSITORY = "ahelal/bender"
|
12
|
+
GITHUB_VERSION = "v0.0.10"
|
13
|
+
|
14
|
+
class Source < Object
|
15
|
+
DEFAULT_AS_USER = true
|
16
|
+
DEFAULT_BOT_NAME = "bender"
|
17
|
+
DEFAULT_MENTION = true
|
18
|
+
DEFAULT_SLACK_UNREAD = false
|
19
|
+
DEFAULT_TEMPLATE_FILENAME = "template_file.txt"
|
20
|
+
|
21
|
+
NotAsUser = proc { |source| source.as_user }
|
22
|
+
|
23
|
+
required :channel, write: AsString
|
24
|
+
required :slack_token, write: AsString
|
25
|
+
|
26
|
+
optional :bot_icon_emoji, write: AsString, guard: NotAsUser
|
27
|
+
optional :bot_icon_url, write: AsString, guard: NotAsUser
|
28
|
+
optional :bot_name, write: AsString, default: proc { DEFAULT_BOT_NAME }, guard: NotAsUser
|
29
|
+
optional :mention, write: AsBoolean, default: proc { DEFAULT_MENTION }, guard: NotAsUser
|
30
|
+
optional :as_user, write: AsBoolean, default: proc { DEFAULT_AS_USER }
|
31
|
+
optional :slack_unread, write: AsBoolean, default: proc { DEFAULT_SLACK_UNREAD }
|
32
|
+
optional :template_filename, write: AsString, default: proc { DEFAULT_TEMPLATE_FILENAME }
|
33
|
+
optional :template, write: AsString
|
34
|
+
optional :grammar, write: AsString
|
35
|
+
|
36
|
+
def initialize(options = {})
|
37
|
+
super(options)
|
38
|
+
super(options) do |this, options|
|
39
|
+
yield this, options if block_given?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class OutParams < Object
|
45
|
+
DEFAULT_REPLY_THREAD = false
|
46
|
+
|
47
|
+
required :path, write: AsString
|
48
|
+
|
49
|
+
optional :reply, write: AsString
|
50
|
+
optional :reply_attachments, write: AsString
|
51
|
+
optional :reply_thread, write: AsBoolean, default: proc { DEFAULT_REPLY_THREAD }
|
52
|
+
end
|
53
|
+
|
54
|
+
optional :source, write: Source
|
55
|
+
|
56
|
+
def initialize(options = {})
|
57
|
+
super(options.merge(type: "bender"))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|