openshift-origin-console 1.3.2 → 1.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/app/assets/stylesheets/_custom.scss +0 -3
- data/app/assets/stylesheets/_forms.scss +13 -8
- data/app/assets/stylesheets/_variables.scss +9 -0
- data/app/assets/stylesheets/console/_application.scss +18 -3
- data/app/assets/stylesheets/console/_core.scss +4 -138
- data/app/controllers/applications_controller.rb +1 -6
- data/app/helpers/console/layout_helper.rb +1 -1
- data/app/helpers/console/model_helper.rb +3 -3
- data/app/models/application_type.rb +3 -23
- data/app/models/quickstart.rb +1 -7
- data/app/views/application_types/show.html.haml +3 -13
- data/app/views/applications/_name.html.haml +9 -9
- data/app/views/applications/get_started.html.haml +0 -5
- data/app/views/cartridge_types/show.html.haml +1 -1
- data/app/views/cartridges/next_steps.html.haml +1 -1
- data/app/views/domains/_form.html.haml +4 -4
- data/config/cartridge_types.yml +4 -0
- data/test/functional/application_types_controller_test.rb +1 -18
- data/test/functional/applications_controller_test.rb +0 -27
- data/test/integration/rest_api/cartridge_type_test.rb +0 -25
- data/test/support/base.rb +1 -0
- data/test/unit/helpers/model_helper_test.rb +15 -0
- data/test/unit/rest_api_test.rb +15 -61
- metadata +4 -6
- data/app/models/application_template.rb +0 -90
- data/app/views/application_templates/_application_template.html.haml +0 -5
@@ -54,7 +54,7 @@ textarea {
|
|
54
54
|
// Identify controls by their labels
|
55
55
|
label {
|
56
56
|
display: block;
|
57
|
-
margin-bottom:
|
57
|
+
margin-bottom: 2px;
|
58
58
|
color: $grayDark;
|
59
59
|
}
|
60
60
|
|
@@ -387,11 +387,8 @@ textarea:focus:required:valid {
|
|
387
387
|
// ------------
|
388
388
|
|
389
389
|
.form-actions {
|
390
|
-
|
391
|
-
|
392
|
-
margin-bottom: $baseLineHeight;
|
393
|
-
background-color: #f5f5f5;
|
394
|
-
border-top: 1px solid #ddd;
|
390
|
+
margin-bottom: 0;
|
391
|
+
padding: 15px 0 10px;
|
395
392
|
@include clearfix(); // Adding clearfix to allow for .pull-right button containers
|
396
393
|
}
|
397
394
|
|
@@ -471,7 +468,7 @@ textarea:focus:required:valid {
|
|
471
468
|
}
|
472
469
|
.add-on,
|
473
470
|
.btn {
|
474
|
-
vertical-align:
|
471
|
+
vertical-align: bottom;
|
475
472
|
@include border-radius(0);
|
476
473
|
}
|
477
474
|
.active {
|
@@ -510,6 +507,7 @@ textarea:focus:required:valid {
|
|
510
507
|
select,
|
511
508
|
.uneditable-input {
|
512
509
|
@include border-radius(0);
|
510
|
+
border-right: 0;
|
513
511
|
}
|
514
512
|
.add-on:first-child,
|
515
513
|
.btn:first-child {
|
@@ -535,6 +533,10 @@ textarea:focus:required:valid {
|
|
535
533
|
@include clearfix();
|
536
534
|
}
|
537
535
|
|
536
|
+
// Overide assigned error state styles from bootstrap
|
537
|
+
.control-group.error .input-prepend .add-on, .control-group.error .input-append .add-on {
|
538
|
+
color: inherit !important;
|
539
|
+
}
|
538
540
|
|
539
541
|
|
540
542
|
// SEARCH FORM
|
@@ -635,7 +637,7 @@ input.search-query {
|
|
635
637
|
|
636
638
|
// Margin to space out fieldsets
|
637
639
|
.control-group {
|
638
|
-
margin-bottom: $baseLineHeight /
|
640
|
+
margin-bottom: $baseLineHeight / 1.5;
|
639
641
|
}
|
640
642
|
|
641
643
|
// Legend collapses margin, so next element is responsible for spacing
|
@@ -699,6 +701,9 @@ legend + .control-group {
|
|
699
701
|
font-size: floor($baseFontSize + 1);
|
700
702
|
padding: 8px 10px;
|
701
703
|
}
|
704
|
+
label.control-label, label {
|
705
|
+
font-size: floor($baseFontSize + 1);
|
706
|
+
}
|
702
707
|
.add-on.middle {
|
703
708
|
padding-left: 0;
|
704
709
|
padding-right: 0;
|
@@ -129,3 +129,12 @@ $horizontalComponentOffset: 180px !default; /* Horizontal forms & lists */
|
|
129
129
|
// -------------------------
|
130
130
|
$placeholderText: $grayLight !default;
|
131
131
|
|
132
|
+
// Console
|
133
|
+
// -------------------------
|
134
|
+
|
135
|
+
$consoleBackground: #1F1F1F;
|
136
|
+
$consoleTableBorderColor: #383838;
|
137
|
+
$consoleTableStriped: rgba(255,255,255,0.02);
|
138
|
+
$consoleTableStripedHover: rgba(255,255,255,0.04);
|
139
|
+
|
140
|
+
|
@@ -179,7 +179,7 @@
|
|
179
179
|
border-top-color: white;
|
180
180
|
}
|
181
181
|
.dropdown-toggle {
|
182
|
-
@include
|
182
|
+
@include box-shadow;
|
183
183
|
}
|
184
184
|
&.open .dropdown-menu {
|
185
185
|
border-radius: 0;
|
@@ -187,8 +187,23 @@
|
|
187
187
|
}
|
188
188
|
|
189
189
|
@media (max-width: 479px) {
|
190
|
-
|
191
|
-
|
190
|
+
|
191
|
+
#new_application .controls {
|
192
|
+
.add-on, .add-on {
|
193
|
+
clear: left;
|
194
|
+
display: block;
|
195
|
+
padding: 8px 0;
|
196
|
+
width: 100% !important;
|
197
|
+
}
|
198
|
+
.add-on.middle {display: none;}
|
199
|
+
.input-prepend, .input-append,
|
200
|
+
.input-prepend input, .input-append input,
|
201
|
+
.input-prepend input, .input-append input {
|
202
|
+
display: block;
|
203
|
+
text-align: center;
|
204
|
+
width: 100%;
|
205
|
+
vertical-align: bottom;
|
192
206
|
}
|
207
|
+
}
|
193
208
|
}
|
194
209
|
|
@@ -1,7 +1,3 @@
|
|
1
|
-
html {
|
2
|
-
background: #101010;
|
3
|
-
}
|
4
|
-
|
5
1
|
.alert {
|
6
2
|
word-wrap: break-word;
|
7
3
|
text-shadow: none;
|
@@ -37,82 +33,6 @@ html {
|
|
37
33
|
color: #cfcfcf;
|
38
34
|
}
|
39
35
|
|
40
|
-
|
41
|
-
// Forms
|
42
|
-
// ----------------------------------------
|
43
|
-
|
44
|
-
input,
|
45
|
-
select,
|
46
|
-
textarea,
|
47
|
-
.uneditable-input {
|
48
|
-
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.075) inset;
|
49
|
-
background: #aaa;
|
50
|
-
border: 1px solid #222;
|
51
|
-
color: #222222;
|
52
|
-
}
|
53
|
-
input:focus, select:focus, textarea:focus {
|
54
|
-
background: #eee; color: #000;
|
55
|
-
box-shadow: none;
|
56
|
-
}
|
57
|
-
.input-prepend-append {
|
58
|
-
@include clearfix()
|
59
|
-
}
|
60
|
-
.input-prepend-append .add-on-first,
|
61
|
-
.input-prepend-append .add-on-last,
|
62
|
-
.input-prepend-append .add-on-middle {
|
63
|
-
background-color: #444;
|
64
|
-
border: 1px solid #222;
|
65
|
-
text-shadow: none;
|
66
|
-
float: left;
|
67
|
-
}
|
68
|
-
.input-prepend-append .add-on-first {border-right: 0;@include border-radius($inputBorderRadius 0 0 $inputBorderRadius);margin-right: -1px;}
|
69
|
-
.input-prepend-append .add-on-last {border-left: 0;@include border-radius(0 $inputBorderRadius $inputBorderRadius 0);margin-left: -1px;}
|
70
|
-
.input-prepend-append input {
|
71
|
-
color: #000;
|
72
|
-
}
|
73
|
-
.input-prepend-append input,
|
74
|
-
.input-prepend-append .add-on-middle {
|
75
|
-
border-top: 1px solid #222;
|
76
|
-
border-bottom: 1px solid #222;
|
77
|
-
margin-bottom: 0;
|
78
|
-
border-radius: 0;
|
79
|
-
border-left: 0;
|
80
|
-
border-right: 0;
|
81
|
-
float: left;
|
82
|
-
}
|
83
|
-
|
84
|
-
input:-moz-placeholder,
|
85
|
-
textarea:-moz-placeholder {
|
86
|
-
color: $grayMedium;
|
87
|
-
background-color: $grayLight;
|
88
|
-
&:focus {
|
89
|
-
color: $grayLight;
|
90
|
-
background-color: $grayLighter;
|
91
|
-
}
|
92
|
-
}
|
93
|
-
|
94
|
-
input:-ms-input-placeholder,
|
95
|
-
textarea:-ms-input-placeholder {
|
96
|
-
color: $grayMedium;
|
97
|
-
background-color: $grayLight;
|
98
|
-
&:focus {
|
99
|
-
color: $grayLight;
|
100
|
-
background-color: $grayLighter;
|
101
|
-
}
|
102
|
-
}
|
103
|
-
|
104
|
-
input::-webkit-input-placeholder,
|
105
|
-
textarea::-webkit-input-placeholder {
|
106
|
-
color: $grayMedium;
|
107
|
-
//background-color: $grayLight;
|
108
|
-
&:focus {
|
109
|
-
color: $grayLight;
|
110
|
-
//background-color: $grayLighter;
|
111
|
-
}
|
112
|
-
}
|
113
|
-
|
114
|
-
|
115
|
-
|
116
36
|
.console-inner-block {
|
117
37
|
background: #222222;
|
118
38
|
color: #B0B0B0;
|
@@ -148,18 +68,10 @@ input[type="radio"], input[type="checkbox"],input[type="image"] {
|
|
148
68
|
}
|
149
69
|
*/
|
150
70
|
|
151
|
-
::-moz-selection {background: #f0f392;color: black;}
|
152
|
-
::-selection {background: #f0f392;color: black;}
|
153
|
-
|
154
71
|
.well {
|
155
72
|
background-color: #242424 /*.*/;
|
156
73
|
}
|
157
|
-
|
158
|
-
background-color: inherit;
|
159
|
-
border: 1px dotted #444;
|
160
|
-
border-radius: 0 0 0 0;
|
161
|
-
color: #babbbc;
|
162
|
-
}
|
74
|
+
|
163
75
|
ol.wizard {
|
164
76
|
margin: 0 0 15px 5px;
|
165
77
|
display: block;
|
@@ -444,10 +356,8 @@ figure {
|
|
444
356
|
|
445
357
|
.form-actions {
|
446
358
|
background-color: transparent;
|
447
|
-
border-top:
|
448
|
-
|
449
|
-
margin-top: 18px;
|
450
|
-
padding: 17px 20px 18px;
|
359
|
+
border-top: 0;
|
360
|
+
padding-top: 0;
|
451
361
|
}
|
452
362
|
|
453
363
|
a.console-link {
|
@@ -773,9 +683,6 @@ $cartridgeBorderWidth: 10px;
|
|
773
683
|
padding-left: 0 !important;
|
774
684
|
display:block;
|
775
685
|
}
|
776
|
-
.control-group-important .input-prepend-append .add-on-first, .control-group-important .input-prepend-append .add-on-last, .control-group-important .input-prepend-append .add-on-middle, .control-group-important .input-prepend-append input, .control-group-important .input-prepend-append input {
|
777
|
-
font-size: inherit;
|
778
|
-
}
|
779
686
|
|
780
687
|
#account-digest {
|
781
688
|
@include expand_for_phone(false);
|
@@ -876,47 +783,6 @@ $cartridgeBorderWidth: 10px;
|
|
876
783
|
|
877
784
|
.control-group.error p+p {padding-left: 100px;}
|
878
785
|
|
879
|
-
/* table customization
|
880
|
-
-----------------------------------------------*/
|
881
|
-
|
882
|
-
.table {
|
883
|
-
th,
|
884
|
-
td {
|
885
|
-
border-color: #383838;
|
886
|
-
}
|
887
|
-
// Account for multiple tbody instances
|
888
|
-
tbody + tbody {
|
889
|
-
border-color: #383838;
|
890
|
-
}
|
891
|
-
}
|
892
|
-
|
893
|
-
.table-bordered {
|
894
|
-
border-color: #383838;
|
895
|
-
th + th,
|
896
|
-
td + td,
|
897
|
-
th + td,
|
898
|
-
td + th {
|
899
|
-
border-color: #383838;
|
900
|
-
}
|
901
|
-
}
|
902
|
-
|
903
|
-
|
904
|
-
.table-striped {
|
905
|
-
tbody {
|
906
|
-
tr:nth-child(odd) td,
|
907
|
-
tr:nth-child(odd) th {
|
908
|
-
background-color: rgba(255,255,255,0.02);
|
909
|
-
}
|
910
|
-
}
|
911
|
-
}
|
912
|
-
.table {
|
913
|
-
tbody tr:hover td,
|
914
|
-
tbody tr:hover th {
|
915
|
-
background-color: rgba(255,255,255,0.04);
|
916
|
-
}
|
917
|
-
}
|
918
|
-
|
919
|
-
.ie9 .table-fixed, .ie8 .table-fixed, .ie7 .table-fixed { table-layout: fixed } // allow td text-overflow
|
920
786
|
|
921
787
|
.sshkey-name {
|
922
788
|
max-width: 80px;
|
@@ -932,7 +798,7 @@ $cartridgeBorderWidth: 10px;
|
|
932
798
|
white-space: nowrap;
|
933
799
|
}
|
934
800
|
|
935
|
-
|
801
|
+
.ie9 .table-fixed, .ie8 .table-fixed, .ie7 .table-fixed { table-layout: fixed } // allow td text-overflow
|
936
802
|
|
937
803
|
|
938
804
|
|
@@ -149,11 +149,7 @@ class ApplicationsController < ConsoleController
|
|
149
149
|
if @application.save
|
150
150
|
messages = @application.remote_results
|
151
151
|
|
152
|
-
|
153
|
-
messages << t.credentials_message if t.credentials
|
154
|
-
end
|
155
|
-
|
156
|
-
redirect_to get_started_application_path(@application, :wizard => true, :template => (@application_type.template.present? || nil)), :flash => {:info_pre => messages}
|
152
|
+
redirect_to get_started_application_path(@application, :wizard => true), :flash => {:info_pre => messages}
|
157
153
|
else
|
158
154
|
logger.debug @application.errors.inspect
|
159
155
|
|
@@ -177,7 +173,6 @@ class ApplicationsController < ConsoleController
|
|
177
173
|
@application = @domain.find_application params[:id]
|
178
174
|
|
179
175
|
@wizard = !params[:wizard].nil?
|
180
|
-
@template = !params[:template].nil?
|
181
176
|
sshkey_uploaded?
|
182
177
|
end
|
183
178
|
end
|
@@ -209,7 +209,7 @@ module Console::LayoutHelper
|
|
209
209
|
items.map{ |c| capture_haml{ yield c }.strip }.to_sentence.html_safe
|
210
210
|
end
|
211
211
|
|
212
|
-
HIDDEN_TAGS = [:featured, :framework, :web_framework, :experimental, :in_development, :
|
212
|
+
HIDDEN_TAGS = [:featured, :framework, :web_framework, :experimental, :in_development, :cartridge]
|
213
213
|
IMPORTANT_TAGS = [:new, :premium]
|
214
214
|
|
215
215
|
def application_type_tags(tags)
|
@@ -66,12 +66,12 @@ module Console::ModelHelper
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def can_scale_application_type(type, capabilities)
|
69
|
-
type.scalable? and capabilities.gears_free >= 2
|
69
|
+
type.scalable? and capabilities.gears_free >= 2
|
70
70
|
end
|
71
71
|
|
72
72
|
def cannot_scale_title(type, capabilities)
|
73
73
|
unless can_scale_application_type(type, capabilities)
|
74
|
-
if type.scalable?
|
74
|
+
if type.scalable?
|
75
75
|
"You need at least two free gears to create a scaling application; you are currently using #{capabilities.consumed_gears} out of #{capabilities.max_gears}."
|
76
76
|
else
|
77
77
|
"This application shares resources and can't be scaled."
|
@@ -96,7 +96,7 @@ module Console::ModelHelper
|
|
96
96
|
[tag, types]
|
97
97
|
end
|
98
98
|
end
|
99
|
-
end.compact
|
99
|
+
end.compact
|
100
100
|
[groups, other]
|
101
101
|
end
|
102
102
|
|
@@ -19,7 +19,6 @@ class ApplicationType
|
|
19
19
|
|
20
20
|
attr_accessor :id, :display_name, :version, :description
|
21
21
|
attr_accessor :cartridges, :initial_git_url, :initial_git_branch, :cartridges_spec
|
22
|
-
attr_accessor :template # DEPRECATED
|
23
22
|
attr_accessor :website, :license, :license_url
|
24
23
|
attr_accessor :tags, :learn_more_url
|
25
24
|
attr_accessor :help_topics
|
@@ -91,14 +90,12 @@ class ApplicationType
|
|
91
90
|
|
92
91
|
def source_priority
|
93
92
|
case source
|
94
|
-
when :template; -1
|
95
93
|
when :cartridge; -2
|
96
94
|
else; 0
|
97
95
|
end
|
98
96
|
end
|
99
97
|
|
100
98
|
def cartridge?; source == :cartridge; end
|
101
|
-
def template?; source == :template; end
|
102
99
|
def quickstart?; source == :quickstart; end
|
103
100
|
|
104
101
|
def matching_cartridges
|
@@ -106,13 +103,9 @@ class ApplicationType
|
|
106
103
|
end
|
107
104
|
|
108
105
|
def >>(app)
|
109
|
-
if
|
110
|
-
|
111
|
-
|
112
|
-
app.cartridges = cartridges if cartridges.present?
|
113
|
-
app.initial_git_url = initial_git_url if initial_git_url
|
114
|
-
app.initial_git_branch = initial_git_branch if initial_git_branch
|
115
|
-
end
|
106
|
+
app.cartridges = cartridges if cartridges.present?
|
107
|
+
app.initial_git_url = initial_git_url if initial_git_url
|
108
|
+
app.initial_git_branch = initial_git_branch if initial_git_branch
|
116
109
|
app
|
117
110
|
end
|
118
111
|
|
@@ -178,7 +171,6 @@ class ApplicationType
|
|
178
171
|
case (match = /^([^!]+)!(.+)/.match(id) || [])[1]
|
179
172
|
when 'quickstart'; from_quickstart(Quickstart.find match[2])
|
180
173
|
when 'cart'; from_cartridge_type(CartridgeType.cached.find match[2])
|
181
|
-
when 'template'; from_application_template(ApplicationTemplate.cached.find match[2])
|
182
174
|
else raise NotFound.new(id)
|
183
175
|
end
|
184
176
|
#find_every(*arguments).find{ |t| t.id == id } or raise NotFound, id
|
@@ -192,18 +184,15 @@ class ApplicationType
|
|
192
184
|
when opts[:search]
|
193
185
|
query = opts[:search].downcase
|
194
186
|
types.concat CartridgeType.cached.standalone
|
195
|
-
types.concat ApplicationTemplate.cached.all
|
196
187
|
types.keep_if &LOCAL_SEARCH.curry[query]
|
197
188
|
types.concat Quickstart.search(query)
|
198
189
|
when opts[:tag]
|
199
190
|
tag = opts[:tag].to_sym rescue (return [])
|
200
191
|
types.concat CartridgeType.cached.standalone
|
201
|
-
types.concat ApplicationTemplate.cached.all unless tag == :cartridge
|
202
192
|
types.keep_if &TAG_FILTER.curry[[tag]]
|
203
193
|
types.concat Quickstart.search(tag.to_s) unless tag == :cartridge
|
204
194
|
else
|
205
195
|
types.concat CartridgeType.cached.standalone
|
206
|
-
types.concat ApplicationTemplate.cached.all
|
207
196
|
types.concat Quickstart.cached.promoted
|
208
197
|
end
|
209
198
|
raise "nil types" unless types
|
@@ -212,7 +201,6 @@ class ApplicationType
|
|
212
201
|
not (t.tags.include?(:blacklist) or (Rails.env.production? and t.tags.include?(:in_development)))
|
213
202
|
end.map do |t|
|
214
203
|
case t
|
215
|
-
when ApplicationTemplate; from_application_template(t)
|
216
204
|
when CartridgeType; from_cartridge_type(t)
|
217
205
|
when Quickstart; from_quickstart(t)
|
218
206
|
end
|
@@ -228,14 +216,6 @@ class ApplicationType
|
|
228
216
|
|
229
217
|
new(attrs, type.persisted?)
|
230
218
|
end
|
231
|
-
def from_application_template(type)
|
232
|
-
attrs = { :id => "template!#{type.name}", :source => :template }
|
233
|
-
[:display_name, :tags, :description, :website, :version, :template, :cartridges, :scalable, :initial_git_url, :initial_git_branch].each do |m|
|
234
|
-
attrs[m] = type.send(m)
|
235
|
-
end
|
236
|
-
|
237
|
-
new(attrs, type.persisted?)
|
238
|
-
end
|
239
219
|
def from_quickstart(type)
|
240
220
|
attrs = { :id => "quickstart!#{type.id}", :source => :quickstart }
|
241
221
|
[:display_name, :tags, :description, :website, :initial_git_url, :initial_git_branch, :cartridges_spec, :priority, :scalable, :learn_more_url].each do |m|
|
data/app/models/quickstart.rb
CHANGED
@@ -41,14 +41,8 @@ class Quickstart < RestApi::Base
|
|
41
41
|
entity_decoded(attributes[:cartridges])
|
42
42
|
end
|
43
43
|
|
44
|
-
# This is a short-term fix for BZ877849
|
45
|
-
# The drupal quickstart nodes need to be augmented with a flag to
|
46
|
-
# indicate whether or not they can be scaled.
|
47
|
-
NON_SCALABLE = Regexp.new(['wordpress','drupal','spring','capedwarf','javaee'].join('|'),true)
|
48
44
|
def scalable
|
49
|
-
|
50
|
-
ensure
|
51
|
-
Rails.logger.debug("Handling #{self.name} quickstart as non-scalable") unless retval
|
45
|
+
(not tags.include?(:not_scalable) rescue true)
|
52
46
|
end
|
53
47
|
alias_method :scalable?, :scalable
|
54
48
|
|
@@ -20,7 +20,6 @@
|
|
20
20
|
#new_application.form-horizontal .control-label { margin-left: 0; }
|
21
21
|
#new_application.form-horizontal .controls { margin-left: 0; }
|
22
22
|
#new_application.form-horizontal .help-block { max-width: inherit; white-space: normal; }
|
23
|
-
#new_application.form-horizontal .controls input { display: inline; }
|
24
23
|
#new_application.form-horizontal .controls > h3 { display: inline-block; margin-top: 0; }
|
25
24
|
#new_application.form-horizontal .form-actions { padding-left: 10px; }
|
26
25
|
}
|
@@ -101,8 +100,9 @@
|
|
101
100
|
.controls
|
102
101
|
%p.help-block
|
103
102
|
- if @application_type.initial_git_url || @advanced
|
104
|
-
Your application will start with
|
105
|
-
this Git repository.
|
103
|
+
Your application will start with an exact copy of the code and configuration provided in
|
104
|
+
this Git repository. OpenShift may expect certain files to exist in certain directories,
|
105
|
+
which may require you to update your repository after creation.
|
106
106
|
- else
|
107
107
|
We'll create a Git code repository in the cloud, and populate it with a set of
|
108
108
|
reasonable defaults.
|
@@ -181,16 +181,6 @@
|
|
181
181
|
- else
|
182
182
|
%span.text-warning= scale_reason
|
183
183
|
|
184
|
-
.control-group
|
185
|
-
.controls
|
186
|
-
- if @application_type.template
|
187
|
-
%p.text-warning
|
188
|
-
After creation, check the repository README for any manual configuration
|
189
|
-
required to secure this application.
|
190
|
-
|
191
|
-
%p
|
192
|
-
%em Note: It may take up to a minute to deploy your application
|
193
|
-
|
194
184
|
= f.buttons do
|
195
185
|
= link_to "Back", application_types_path, :class => 'btn'
|
196
186
|
= f.commit_button :button_html => { :disabled => @disabled }
|
@@ -1,27 +1,27 @@
|
|
1
|
-
.input-prepend-append
|
2
|
-
%span.add-on
|
1
|
+
.input-prepend.input-append
|
2
|
+
%span.add-on http://
|
3
3
|
|
4
4
|
= form.text_field :name,
|
5
5
|
:value => "#{application.name}",
|
6
6
|
:autofocus => true,
|
7
|
-
:
|
7
|
+
:size => nil,
|
8
8
|
:placeholder => 'Application name',
|
9
|
-
:class => "application_name #{'error' if application.errors.include? :name}"
|
9
|
+
:class => "application_name span3 #{'error' if application.errors.include? :name}"
|
10
10
|
|
11
11
|
-# If the user has a domain, use it, otherwise prompt them for that field
|
12
12
|
- if @domain and @domain.persisted?
|
13
13
|
|
14
|
-
%span.add-on
|
14
|
+
%span.add-on> -#{@domain.name}.#{RestApi.application_domain_suffix}
|
15
15
|
|
16
16
|
- else
|
17
17
|
|
18
|
-
%span.add-on
|
18
|
+
%span.add-on.middle> –
|
19
19
|
= form.text_field :domain_name,
|
20
20
|
:value => "#{application.domain_name}",
|
21
21
|
:placeholder => 'Namespace',
|
22
|
-
:
|
23
|
-
:class => "domain_name #{'error' if application.errors.include? :domain_name}"
|
24
|
-
%span.add-on
|
22
|
+
:size => nil,
|
23
|
+
:class => "domain_name span3 #{'error' if application.errors.include? :domain_name}"
|
24
|
+
%span.add-on>= ".#{RestApi.application_domain_suffix}"
|
25
25
|
|
26
26
|
- unless @domain and @domain.persisted?
|
27
27
|
%p.help-block
|
@@ -25,11 +25,6 @@
|
|
25
25
|
- else
|
26
26
|
If your application exposes services to the Internet they will be available at
|
27
27
|
|
28
|
-
- if @template
|
29
|
-
.alert.alert-info
|
30
|
-
Your application is currently being created. Preconfigured applications take a little longer to get ready.
|
31
|
-
If you try to access your application and get a 503 error, it means the deployment is in progress.
|
32
|
-
|
33
28
|
%p.well.application-url.larger
|
34
29
|
= link_to @application.web_url, @application.web_url, :target => '_blank'
|
35
30
|
|
@@ -17,7 +17,7 @@
|
|
17
17
|
Most of the capabilities of OpenShift are exposed through our command line tool, <code>rhc</code>.
|
18
18
|
Whether it's adding cartridges, checking uptime, or pulling log files from
|
19
19
|
the server, you can quickly put a finger on the pulse of your application.
|
20
|
-
#{link_to "Follow these steps to install the client",
|
20
|
+
#{link_to "Follow these steps to install the client", getting_started_guide_url}
|
21
21
|
on Linux, Mac OS X, or Windows.
|
22
22
|
|
23
23
|
%p
|
@@ -1,11 +1,11 @@
|
|
1
1
|
= semantic_form_for domain, :url => domain_path, :simple => true do |f|
|
2
2
|
= f.semantic_errors :name
|
3
3
|
.control-group.control-group-important{:class => domain.errors[:name].present? || domain.errors[:namespace].present? ? 'error' : '', :id => "domain_name_group", :data => domain.errors[:name].present? || domain.errors[:namespace].present? ? {:"server-error" => 'server-error'} : {}}
|
4
|
-
.controls
|
5
|
-
.input-prepend-append
|
6
|
-
%span.add-on
|
4
|
+
.controls.first
|
5
|
+
.input-prepend.input-append
|
6
|
+
%span.add-on> http://applicationname–
|
7
7
|
= f.text_field :name, :autofocus => true, :placeholder => 'Namespace', :class => 'domain_name'
|
8
|
-
%span.add-on
|
8
|
+
%span.add-on>= RestApi.application_domain_suffix
|
9
9
|
.help-block Your namespace must be letters or numbers with no spaces or symbols.
|
10
10
|
= f.buttons do
|
11
11
|
= link_to "Cancel", account_path, :class => 'btn'
|
data/config/cartridge_types.yml
CHANGED
@@ -22,14 +22,6 @@ class ApplicationTypesControllerTest < ActionController::TestCase
|
|
22
22
|
assert groups.first[1].present?
|
23
23
|
end
|
24
24
|
|
25
|
-
test "should be able to find templates" do
|
26
|
-
with_unique_user
|
27
|
-
types = ApplicationType.all
|
28
|
-
(templates,) = types.partition{|t| t.template?}
|
29
|
-
omit("No templates have been registered on this server") if templates.empty?
|
30
|
-
assert_not_equal 0, templates.length, "There should be templates to test against"
|
31
|
-
end
|
32
|
-
|
33
25
|
test "should be able to find quickstarts" do
|
34
26
|
with_unique_user
|
35
27
|
types = ApplicationType.all
|
@@ -62,7 +54,7 @@ class ApplicationTypesControllerTest < ActionController::TestCase
|
|
62
54
|
assert assigns(:application)
|
63
55
|
assert assigns(:domain)
|
64
56
|
assert css_select('input#application_domain_name').present?
|
65
|
-
if t.tags.include?(:
|
57
|
+
if t.tags.include?(:not_scalable) or t.id == 'diy-0.1'
|
66
58
|
# Sanity-check known non-scalable types
|
67
59
|
assert_equal false, t.scalable?
|
68
60
|
elsif t.id == 'php-5.3'
|
@@ -88,15 +80,6 @@ class ApplicationTypesControllerTest < ActionController::TestCase
|
|
88
80
|
assert_standard_show_type(type)
|
89
81
|
end
|
90
82
|
|
91
|
-
test "should show type page for application template" do
|
92
|
-
with_unique_user
|
93
|
-
type = ApplicationType.all.select(&:template?).sample(1).first
|
94
|
-
omit("No templates registered on this server") if type.nil?
|
95
|
-
|
96
|
-
get :show, :id => type.id
|
97
|
-
assert_standard_show_type(type)
|
98
|
-
end
|
99
|
-
|
100
83
|
test "should handle invalid quickstart page" do
|
101
84
|
with_unique_user
|
102
85
|
type = Quickstart.new(:id => 'test', :name => '', :cartridges => '[{')
|
@@ -6,19 +6,6 @@ class ApplicationsControllerTest < ActionController::TestCase
|
|
6
6
|
# in applications_controller_sanity_test
|
7
7
|
end
|
8
8
|
|
9
|
-
test 'template create and destroy' do
|
10
|
-
with_unique_domain
|
11
|
-
type = ApplicationType.all.select(&:template?).sample(1).first
|
12
|
-
omit("No templates are installed on this server") if type.nil?
|
13
|
-
post(:create, {:application => get_post_form(type.id)})
|
14
|
-
|
15
|
-
assert app = assigns(:application)
|
16
|
-
assert app.errors.empty?, app.errors.inspect
|
17
|
-
assert app.persisted?, app.inspect
|
18
|
-
|
19
|
-
app.destroy
|
20
|
-
end
|
21
|
-
|
22
9
|
test 'should redirect new to types' do
|
23
10
|
with_configured_user
|
24
11
|
get :new
|
@@ -271,20 +258,6 @@ class ApplicationsControllerTest < ActionController::TestCase
|
|
271
258
|
assert_select 'h1', /Application 'idontexist' does not exist/
|
272
259
|
end
|
273
260
|
|
274
|
-
test 'should combine messages correctly for template creation' do
|
275
|
-
with_unique_domain
|
276
|
-
template = ApplicationType.all.select(&:template?).select{ |t| t.template.credentials_message }.sample(1).first
|
277
|
-
omit("No templates installed on this system") if template.nil?
|
278
|
-
saved = states('saved').starts_as('no')
|
279
|
-
Application.any_instance.expects(:save).returns(true).then(saved.is('yes'))
|
280
|
-
Application.any_instance.expects(:persisted?).at_least_once.returns(false).when(saved.is('no'))
|
281
|
-
Application.any_instance.expects(:persisted?).at_least_once.returns(true).when(saved.is('yes'))
|
282
|
-
Application.any_instance.expects(:remote_results).at_least_once.returns(['message'])
|
283
|
-
post(:create, {:application => get_post_form(template.id)})
|
284
|
-
|
285
|
-
assert_equal ['message', template.template.credentials_message], flash[:info_pre]
|
286
|
-
end
|
287
|
-
|
288
261
|
test 'invalid destroy should render page' do
|
289
262
|
Application.any_instance.expects(:destroy).returns(false)
|
290
263
|
delete :destroy, :id => with_app.name
|
@@ -67,20 +67,6 @@ class RestApiCartridgeTypeTest < ActiveSupport::TestCase
|
|
67
67
|
log_types(types)
|
68
68
|
|
69
69
|
assert types[0].id.starts_with?('cart!jbosseap'), types[0].id
|
70
|
-
|
71
|
-
type = types.find(&:template?)
|
72
|
-
omit("No templates defined on this server") if type.nil?
|
73
|
-
|
74
|
-
template = type.template
|
75
|
-
assert template.name
|
76
|
-
assert template.description
|
77
|
-
assert template.version
|
78
|
-
assert template.website
|
79
|
-
assert template.git_url
|
80
|
-
assert template.git_project_url
|
81
|
-
assert_equal type.id, "template!#{template.name}"
|
82
|
-
assert template.git_project_url
|
83
|
-
assert_same template.tags, template.tags
|
84
70
|
end
|
85
71
|
|
86
72
|
test 'sort cartridges' do
|
@@ -121,17 +107,6 @@ class RestApiCartridgeTypeTest < ActiveSupport::TestCase
|
|
121
107
|
assert missing.empty?
|
122
108
|
end
|
123
109
|
|
124
|
-
# Currently /application_templates/<string>.json can return an array
|
125
|
-
# if the value is not a properly formatted ID. This is questionable,
|
126
|
-
# and this test is only to protect us in the case that we have code
|
127
|
-
# depending on that behavior. If this behavior is moved to a new
|
128
|
-
# route then we can remove this.
|
129
|
-
test 'application template names returned by server' do
|
130
|
-
template = ApplicationTemplate.first(:from => :wordpress)
|
131
|
-
omit("No templates defined on this server") unless template
|
132
|
-
assert_equal 'WordPress', template.display_name
|
133
|
-
end
|
134
|
-
|
135
110
|
test 'match cartridges' do
|
136
111
|
assert_equal [], CartridgeType.cached.matches('bra').map(&:name)
|
137
112
|
assert_equal ['ruby-1.9','ruby-1.8'], CartridgeType.cached.matches('ruby').map(&:name)
|
data/test/support/base.rb
CHANGED
@@ -35,6 +35,7 @@ class ActiveSupport::TestCase
|
|
35
35
|
def self.uses_http_mock(sym=:always)
|
36
36
|
require 'active_resource/persistent_http_mock'
|
37
37
|
self.module_eval do
|
38
|
+
setup{ RestApi.stubs(:application_domain_suffix).returns('test.rhcloud.com') }
|
38
39
|
setup{ ActiveResource::HttpMock.enabled = true } unless sym == :sometimes
|
39
40
|
teardown do
|
40
41
|
ActiveResource::HttpMock.reset!
|
@@ -58,4 +58,19 @@ class Console::ModelHelperTest < ActionView::TestCase
|
|
58
58
|
},
|
59
59
|
scale_to_options(stub(:supported_scales_from => 1, :supported_scales_to => -1), 6, 5))
|
60
60
|
end
|
61
|
+
|
62
|
+
Tagged = Struct.new(:tags)
|
63
|
+
|
64
|
+
def test_in_groups_by_tag
|
65
|
+
t1 = Tagged.new([:ruby, :php])
|
66
|
+
t2 = Tagged.new([:ruby])
|
67
|
+
|
68
|
+
groups, others = in_groups_by_tag([t1], [:ruby])
|
69
|
+
assert_equal [t1], others
|
70
|
+
assert groups.empty?
|
71
|
+
|
72
|
+
groups, others = in_groups_by_tag([t1, t2], [:ruby])
|
73
|
+
assert_equal [[:ruby, [t1, t2]]], groups
|
74
|
+
assert others.empty?
|
75
|
+
end
|
61
76
|
end
|
data/test/unit/rest_api_test.rb
CHANGED
@@ -999,11 +999,6 @@ class RestApiTest < ActiveSupport::TestCase
|
|
999
999
|
assert_equal false, non_scalable_type.scalable?
|
1000
1000
|
end
|
1001
1001
|
|
1002
|
-
def test_application_template_scalable_check
|
1003
|
-
assert app_template = ApplicationTemplate.new
|
1004
|
-
assert_equal false, app_template.scalable?
|
1005
|
-
end
|
1006
|
-
|
1007
1002
|
def test_cartridge_type_find
|
1008
1003
|
ActiveResource::HttpMock.respond_to do |mock|
|
1009
1004
|
mock.get '/broker/rest/cartridges.json', anonymous_json_header, [
|
@@ -1209,9 +1204,6 @@ class RestApiTest < ActiveSupport::TestCase
|
|
1209
1204
|
{:name => 'php-5.3', :type => 'standalone', :tags => [:framework]},
|
1210
1205
|
{:name => 'blacklist', :type => 'standalone', :tags => [:framework, :blacklist]},
|
1211
1206
|
].to_json
|
1212
|
-
|
1213
|
-
mock.get '/broker/rest/application_templates.json', anonymous_json_header, [
|
1214
|
-
].to_json
|
1215
1207
|
end
|
1216
1208
|
|
1217
1209
|
# For this test, stub the scalability logic; we test it separately
|
@@ -1231,54 +1223,6 @@ class RestApiTest < ActiveSupport::TestCase
|
|
1231
1223
|
assert_raise(ApplicationType::NotFound) { ApplicationType.find('blacklist') }
|
1232
1224
|
end
|
1233
1225
|
|
1234
|
-
def test_application_templates
|
1235
|
-
mock_quickstart_disabled
|
1236
|
-
ActiveResource::HttpMock.respond_to(false) do |mock|
|
1237
|
-
mock.get '/broker/rest/cartridges.json', anonymous_json_header, [
|
1238
|
-
].to_json
|
1239
|
-
|
1240
|
-
mock.get '/broker/rest/application_templates.json', anonymous_json_header, [
|
1241
|
-
{
|
1242
|
-
:name => 'blacklist',
|
1243
|
-
:tags => [:framework, :blacklist],
|
1244
|
-
:metadata => {},
|
1245
|
-
:descriptor_yaml => ''
|
1246
|
-
},
|
1247
|
-
{
|
1248
|
-
:name => 'rails',
|
1249
|
-
:tags => [:framework, :ruby, :rails, :in_development],
|
1250
|
-
:descriptor_yaml => YAML.dump({
|
1251
|
-
'Name' => "rails"
|
1252
|
-
}),
|
1253
|
-
:metadata => {
|
1254
|
-
:attributes => {
|
1255
|
-
}.to_json
|
1256
|
-
},
|
1257
|
-
:display_name => "Ruby on Rails",
|
1258
|
-
:uuid => '1234'
|
1259
|
-
}
|
1260
|
-
].to_json
|
1261
|
-
end
|
1262
|
-
|
1263
|
-
types = ApplicationType.find :all
|
1264
|
-
assert_equal 1, types.length
|
1265
|
-
|
1266
|
-
assert_equal 'Ruby on Rails', types[0].display_name
|
1267
|
-
|
1268
|
-
types.each do |type|
|
1269
|
-
assert a = ApplicationType.find(type.id)
|
1270
|
-
assert_equal type.id, a.id
|
1271
|
-
assert_equal type.description, a.description
|
1272
|
-
assert_equal type.categories, a.categories
|
1273
|
-
end
|
1274
|
-
|
1275
|
-
assert_raise(ApplicationType::NotFound) { ApplicationType.find('blacklist') }
|
1276
|
-
|
1277
|
-
# template is in_development and excluded
|
1278
|
-
Rails.env.expects(:production?).returns(true)
|
1279
|
-
assert ApplicationType.find(:all).empty?
|
1280
|
-
end
|
1281
|
-
|
1282
1226
|
def test_application_job_url
|
1283
1227
|
a = Application.new :build_job_url => "https://test/test"
|
1284
1228
|
assert_equal 'https://test/test', a.build_job_url
|
@@ -1417,11 +1361,12 @@ class RestApiTest < ActiveSupport::TestCase
|
|
1417
1361
|
assert group1.send(:move_features, group2) # nothing is moved, but group1 is still empty and should be purged
|
1418
1362
|
end
|
1419
1363
|
|
1420
|
-
def a_quickstart
|
1364
|
+
def a_quickstart(additional_tags=[])
|
1365
|
+
tags = ["blog", "instant_app", "php", "wordpress"].concat(additional_tags).join(", ")
|
1421
1366
|
quickstart = {data:[
|
1422
1367
|
{quickstart:{
|
1423
1368
|
body:"<p>An awesome blog hosting platform with a rich ecosystem<\/p>",
|
1424
|
-
summary:"An awesome blog hosting platform with a rich ecosystem",
|
1369
|
+
summary: "An awesome blog hosting platform with a rich ecosystem",
|
1425
1370
|
id:"12069",
|
1426
1371
|
href:"\/community\/content\/wordpress-34",
|
1427
1372
|
name:"Wordpress 3.4",
|
@@ -1429,17 +1374,17 @@ class RestApiTest < ActiveSupport::TestCase
|
|
1429
1374
|
cartridges:"php-5.3, mysql-5.1",
|
1430
1375
|
initial_git_url:"https:\/\/github.com\/openshift\/wordpress-example",
|
1431
1376
|
language:"PHP",
|
1432
|
-
tags:
|
1377
|
+
tags: tags,
|
1433
1378
|
website:"https:\/\/www.wordpress.org"
|
1434
1379
|
}}
|
1435
1380
|
]}
|
1436
1381
|
end
|
1437
1382
|
|
1438
|
-
def mock_quickstart
|
1383
|
+
def mock_quickstart(additional_tags=[])
|
1439
1384
|
Quickstart.reset!
|
1440
1385
|
RestApi.reset!
|
1441
1386
|
|
1442
|
-
quickstart = a_quickstart
|
1387
|
+
quickstart = a_quickstart(additional_tags)
|
1443
1388
|
|
1444
1389
|
ActiveResource::HttpMock.respond_to do |mock|
|
1445
1390
|
mock.get '/broker/rest/api.json', anonymous_json_header, {:data => {
|
@@ -1525,6 +1470,7 @@ class RestApiTest < ActiveSupport::TestCase
|
|
1525
1470
|
assert q = Quickstart.promoted.first
|
1526
1471
|
assert_equal "Wordpress 3.4", q.name
|
1527
1472
|
assert_equal "12069", q.id
|
1473
|
+
assert q.scalable?
|
1528
1474
|
assert q.website
|
1529
1475
|
assert_equal 'php-5.3, mysql-5.1', q.cartridges_spec
|
1530
1476
|
assert q.initial_git_url
|
@@ -1532,6 +1478,14 @@ class RestApiTest < ActiveSupport::TestCase
|
|
1532
1478
|
assert q.updated > 1.year.ago
|
1533
1479
|
end
|
1534
1480
|
|
1481
|
+
def test_non_scalable_quickstarts
|
1482
|
+
mock_quickstart(['not_scalable'])
|
1483
|
+
|
1484
|
+
assert_equal 1, Quickstart.promoted.length
|
1485
|
+
assert q = Quickstart.promoted.first
|
1486
|
+
assert_equal false, q.scalable?
|
1487
|
+
end
|
1488
|
+
|
1535
1489
|
def test_quickstart_disabled
|
1536
1490
|
mock_quickstart_disabled
|
1537
1491
|
assert Quickstart.disabled?
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openshift-origin-console
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 1.3.
|
9
|
+
- 3
|
10
|
+
version: 1.3.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Clayton Coleman
|
@@ -21,7 +21,7 @@ autorequire:
|
|
21
21
|
bindir: bin
|
22
22
|
cert_chain: []
|
23
23
|
|
24
|
-
date:
|
24
|
+
date: 2013-01-10 00:00:00 -05:00
|
25
25
|
default_executable:
|
26
26
|
dependencies:
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -125,7 +125,6 @@ files:
|
|
125
125
|
- README.md
|
126
126
|
- Rakefile
|
127
127
|
- app/views/shared/_tracking.html.haml
|
128
|
-
- app/views/application_templates/_application_template.html.haml
|
129
128
|
- app/views/account/_domain.html.haml
|
130
129
|
- app/views/account/_user.html.haml
|
131
130
|
- app/views/account/show.html.haml
|
@@ -181,7 +180,6 @@ files:
|
|
181
180
|
- app/models/application_associations.rb
|
182
181
|
- app/models/rest_api.rb
|
183
182
|
- app/models/alias.rb
|
184
|
-
- app/models/application_template.rb
|
185
183
|
- app/models/rest_api/log_subscriber.rb
|
186
184
|
- app/models/rest_api/cacheable.rb
|
187
185
|
- app/models/rest_api/railties/controller_runtime.rb
|
@@ -1,90 +0,0 @@
|
|
1
|
-
class ApplicationTemplate < RestApi::Base
|
2
|
-
allow_anonymous
|
3
|
-
|
4
|
-
schema do
|
5
|
-
string :descriptor_yaml, :display_name
|
6
|
-
end
|
7
|
-
|
8
|
-
custom_id :name
|
9
|
-
|
10
|
-
[:description, :website, :version, :git_url, :git_project_url].each do |s|
|
11
|
-
define_attribute_method s
|
12
|
-
define_method s do
|
13
|
-
metadata.attributes[s]
|
14
|
-
end
|
15
|
-
end
|
16
|
-
{:name => 'Name', :provides => 'Requires'}.each_pair do |s,v|
|
17
|
-
define_attribute_method s
|
18
|
-
define_method s do
|
19
|
-
descriptor[v]
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def descriptor
|
24
|
-
@descriptor ||= YAML.load(descriptor_yaml) || {}
|
25
|
-
end
|
26
|
-
|
27
|
-
def display_name
|
28
|
-
attributes['display_name'] || name
|
29
|
-
end
|
30
|
-
def tags
|
31
|
-
@tags ||= super.map{|t| t.to_sym} << :template
|
32
|
-
end
|
33
|
-
alias_method :categories, :tags
|
34
|
-
|
35
|
-
def provides
|
36
|
-
Array(super)
|
37
|
-
end
|
38
|
-
|
39
|
-
def template
|
40
|
-
self
|
41
|
-
end
|
42
|
-
|
43
|
-
def credentials
|
44
|
-
creds = metadata.attributes[:credentials]
|
45
|
-
creds.map{|x| x.attributes.to_hash } unless creds.nil?
|
46
|
-
end
|
47
|
-
|
48
|
-
def credentials_message
|
49
|
-
creds = credentials
|
50
|
-
return if creds.blank?
|
51
|
-
|
52
|
-
str = "Your application contains pre-configured accounts, here are their credentials. " +
|
53
|
-
"You may want to change them as soon as possible.\n"
|
54
|
-
|
55
|
-
credentials.each do |cred|
|
56
|
-
str << "\n"
|
57
|
-
[:username, :password].each do |type|
|
58
|
-
str << "%s: %s\n" % [type.to_s.upcase,cred[type.to_s]]
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
str
|
63
|
-
end
|
64
|
-
|
65
|
-
def scalable
|
66
|
-
false
|
67
|
-
end
|
68
|
-
alias_method :scalable?, :scalable
|
69
|
-
|
70
|
-
def cartridges
|
71
|
-
@cartridges ||= descriptor['Requires'] || []
|
72
|
-
end
|
73
|
-
|
74
|
-
alias_method :initial_git_url, :git_url
|
75
|
-
def initial_git_branch
|
76
|
-
nil
|
77
|
-
end
|
78
|
-
|
79
|
-
cache_find_method :single, lambda{ |*args| [:template, :find, :by_id, args.shift] }
|
80
|
-
cache_find_method :every
|
81
|
-
|
82
|
-
protected
|
83
|
-
def self.find_single(s, opts=nil)
|
84
|
-
all(opts).find{ |t| t.name == s }
|
85
|
-
end
|
86
|
-
|
87
|
-
def self.disabled?
|
88
|
-
!RestApi.info.link('LIST_TEMPLATES') rescue true
|
89
|
-
end
|
90
|
-
end
|