passenger 5.1.6 → 5.1.7

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

@@ -77,7 +77,7 @@ private:
77
77
  }
78
78
 
79
79
  UPDATE_TRACE_POINT();
80
- while (!this_thread::interruption_requested()) {
80
+ while (!boost::this_thread::interruption_requested()) {
81
81
  char buf[1024 * 8];
82
82
  ssize_t ret;
83
83
 
@@ -336,7 +336,11 @@ private:
336
336
  prepareRequest(pingURL);
337
337
 
338
338
  curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
339
- if (curl_easy_perform(curl) != 0) {
339
+ CURLcode code;
340
+ if (CURLE_OK == (code = setCurlDefaultCaInfo(curl))) {
341
+ code = curl_easy_perform(curl);
342
+ }
343
+ if (code != 0) {
340
344
  setPingError(
341
345
  "Could not ping Union Station gateway server " +
342
346
  ip + ": " + lastCurlErrorMessage);
@@ -406,7 +410,10 @@ private:
406
410
  P_DEBUG("Sending Union Station packet: key=" << item.unionStationKey <<
407
411
  ", node=" << item.nodeName << ", category=" << item.category <<
408
412
  ", compressedDataSize=" << item.data.size());
409
- CURLcode code = curl_easy_perform(curl);
413
+ CURLcode code;
414
+ if (CURLE_OK == (code = setCurlDefaultCaInfo(curl))) {
415
+ code = curl_easy_perform(curl);
416
+ }
410
417
  curl_formfree(post);
411
418
 
412
419
  if (code == CURLE_OK) {
@@ -44,10 +44,15 @@ class Store;
44
44
 
45
45
  enum Type {
46
46
  STRING_TYPE,
47
+ PASSWORD_TYPE, // Like STRING_TYPE, but inspect() won't show its value
47
48
  INT_TYPE,
48
49
  UINT_TYPE,
49
50
  FLOAT_TYPE,
50
51
  BOOL_TYPE,
52
+
53
+ ARRAY_TYPE,
54
+ STRING_ARRAY_TYPE,
55
+
51
56
  UNKNOWN_TYPE
52
57
  };
53
58
 
@@ -0,0 +1,76 @@
1
+ /*
2
+ * Phusion Passenger - https://www.phusionpassenger.com/
3
+ * Copyright (c) 2017 Phusion Holding B.V.
4
+ *
5
+ * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
+ * trademarks of Phusion Holding B.V.
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+ #ifndef _PASSENGER_CONFIG_KIT_DUMMY_TRANSLATOR_H_
27
+ #define _PASSENGER_CONFIG_KIT_DUMMY_TRANSLATOR_H_
28
+
29
+ #include <vector>
30
+ #include <ConfigKit/Common.h>
31
+ #include <StaticString.h>
32
+
33
+ namespace Passenger {
34
+ namespace ConfigKit {
35
+
36
+ using namespace std;
37
+
38
+
39
+ /**
40
+ * A translator that does nothing.
41
+ *
42
+ * You can learn more about translators in the ConfigKit README, section
43
+ * "The special problem of overlapping configuration names and translation".
44
+ */
45
+ class DummyTranslator {
46
+ public:
47
+ Json::Value translate(const Json::Value &doc) const {
48
+ return doc;
49
+ }
50
+
51
+ Json::Value reverseTranslate(const Json::Value &doc) const {
52
+ return doc;
53
+ }
54
+
55
+ vector<Error> translate(const vector<Error> &errors) const {
56
+ return errors;
57
+ }
58
+
59
+ vector<Error> reverseTranslate(const vector<Error> &errors) const {
60
+ return errors;
61
+ }
62
+
63
+ StaticString translateOne(const StaticString &key) const {
64
+ return key;
65
+ }
66
+
67
+ StaticString reverseTranslateOne(const StaticString &key) const {
68
+ return key;
69
+ }
70
+ };
71
+
72
+
73
+ } // namespace ConfigKit
74
+ } // namespace Passenger
75
+
76
+ #endif /* _PASSENGER_CONFIG_KIT_DUMMY_TRANSLATOR_H_ */
@@ -0,0 +1,166 @@
1
+ /*
2
+ * Phusion Passenger - https://www.phusionpassenger.com/
3
+ * Copyright (c) 2017 Phusion Holding B.V.
4
+ *
5
+ * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
+ * trademarks of Phusion Holding B.V.
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+ #ifndef _PASSENGER_CONFIG_KIT_PREFIX_TRANSLATOR_H_
27
+ #define _PASSENGER_CONFIG_KIT_PREFIX_TRANSLATOR_H_
28
+
29
+ #include <boost/bind.hpp>
30
+ #include <cassert>
31
+ #include <string>
32
+ #include <vector>
33
+ #include <jsoncpp/json.h>
34
+
35
+ #include <ConfigKit/Common.h>
36
+ #include <StaticString.h>
37
+
38
+ namespace Passenger {
39
+ namespace ConfigKit {
40
+
41
+ using namespace std;
42
+
43
+
44
+ /**
45
+ * A translator that translates keys by adding a prefix.
46
+ *
47
+ * You can learn more about translators in the ConfigKit README, section
48
+ * "The special problem of overlapping configuration names and translation".
49
+ */
50
+ class PrefixTranslator {
51
+ private:
52
+ string prefix;
53
+ bool finalized;
54
+
55
+ string translateErrorKey(const StaticString &key) const {
56
+ return "{{" + translateOne(key) + "}}";
57
+ }
58
+
59
+ string reverseTranslateErrorKey(const StaticString &key) const {
60
+ return "{{" + reverseTranslateOne(key) + "}}";
61
+ }
62
+
63
+ public:
64
+ PrefixTranslator()
65
+ : finalized(false)
66
+ { }
67
+
68
+ PrefixTranslator(const string &_prefix)
69
+ : prefix(_prefix),
70
+ finalized(true)
71
+ { }
72
+
73
+ void setPrefixAndFinalize(const string &_prefix) {
74
+ assert(!finalized);
75
+ prefix = _prefix;
76
+ finalized = true;
77
+ }
78
+
79
+ bool isFinalized() const {
80
+ return finalized;
81
+ }
82
+
83
+ Json::Value translate(const Json::Value &doc) const {
84
+ assert(finalized);
85
+ Json::Value result(Json::objectValue);
86
+ Json::Value::const_iterator it, end = doc.end();
87
+
88
+ for (it = doc.begin(); it != end; it++) {
89
+ const char *keyEnd;
90
+ const char *key = it.memberName(&keyEnd);
91
+ result[translateOne(StaticString(key, keyEnd - key))] = *it;
92
+ }
93
+
94
+ return result;
95
+ }
96
+
97
+ Json::Value reverseTranslate(const Json::Value &doc) const {
98
+ assert(finalized);
99
+ Json::Value result(Json::objectValue);
100
+ Json::Value::const_iterator it, end = doc.end();
101
+
102
+ for (it = doc.begin(); it != end; it++) {
103
+ const char *keyEnd;
104
+ const char *key = it.memberName(&keyEnd);
105
+ result[reverseTranslateOne(StaticString(key, keyEnd - key))] = *it;
106
+ }
107
+
108
+ return result;
109
+ }
110
+
111
+ vector<Error> translate(const vector<Error> &errors) const {
112
+ assert(finalized);
113
+ vector<Error> result;
114
+ vector<Error>::const_iterator it, end = errors.end();
115
+ Error::KeyProcessor keyProcessor =
116
+ boost::bind(&PrefixTranslator::translateErrorKey, this,
117
+ boost::placeholders::_1);
118
+
119
+ for (it = errors.begin(); it != end; it++) {
120
+ const Error &error = *it;
121
+ result.push_back(Error(error.getMessage(keyProcessor)));
122
+ }
123
+
124
+ return result;
125
+ }
126
+
127
+ vector<Error> reverseTranslate(const vector<Error> &errors) const {
128
+ assert(finalized);
129
+ vector<Error> result;
130
+ vector<Error>::const_iterator it, end = errors.end();
131
+ Error::KeyProcessor keyProcessor =
132
+ boost::bind(&PrefixTranslator::reverseTranslateErrorKey, this,
133
+ boost::placeholders::_1);
134
+
135
+ for (it = errors.begin(); it != end; it++) {
136
+ const Error &error = *it;
137
+ result.push_back(Error(error.getMessage(keyProcessor)));
138
+ }
139
+
140
+ return result;
141
+ }
142
+
143
+ string translateOne(const StaticString &key) const {
144
+ assert(finalized);
145
+ if (key.substr(0, prefix.size()) == prefix) {
146
+ return key.substr(prefix.size());
147
+ } else {
148
+ return key;
149
+ }
150
+ }
151
+
152
+ string reverseTranslateOne(const StaticString &key) const {
153
+ assert(finalized);
154
+ if (key.substr(0, prefix.size()) != prefix) {
155
+ return prefix + key;
156
+ } else {
157
+ return key;
158
+ }
159
+ }
160
+ };
161
+
162
+
163
+ } // namespace ConfigKit
164
+ } // namespace Passenger
165
+
166
+ #endif /* _PASSENGER_CONFIG_KIT_PREFIX_TRANSLATOR_H_ */
@@ -4,34 +4,41 @@ ConfigKit is a configuration management system that lets you define configuratio
4
4
 
5
5
  **Table of contents:**
6
6
 
7
- * Motivations
8
- - Configuration flow from high-level to low-level with a minimum of repeated code
9
- - Unifying configuration management
10
- * Status inside the Passenger codebase
11
- * Features and class overview
12
- - ConfigKit::Schema
13
- - ConfigKit::Store
14
- - Translators
15
- * Using the schema
16
- - Defining the schema
17
- - Defining default values
18
- - Defining custom validators
19
- - Inspecting the schema
20
- * Using the store
21
- - Putting data in the store
22
- - Updating data
23
- - Unregistered keys are ignored
24
- - Deleting data
25
- - Fetching data
26
- - Default values
27
- - Inspecting all data
28
- * Putting it all together: synchronous version
29
- - SecurityChecker example: a configurable, low-level component
30
- - DnsQuerier example: a low-level component with post-configuration application operations
31
- - Downloader example: a high-level component that combines subcomponents
32
- - The special problem of conflicting overlapping configuration names and translation
33
- - Code example
34
- * Putting it all together: asynchronous version
7
+ <!-- MarkdownTOC depth=3 autolink="true" bracket="round" -->
8
+
9
+ - [Motivations](#motivations)
10
+ - [Configuration flow from high-level to low-level with a minimum of repeated code](#configuration-flow-from-high-level-to-low-level-with-a-minimum-of-repeated-code)
11
+ - [Unifying configuration management](#unifying-configuration-management)
12
+ - [Status inside the Passenger codebase](#status-inside-the-passenger-codebase)
13
+ - [Features and class overview](#features-and-class-overview)
14
+ - [ConfigKit::Schema](#configkitschema)
15
+ - [ConfigKit::Store](#configkitstore)
16
+ - [Translators](#translators)
17
+ - [Using the schema](#using-the-schema)
18
+ - [Defining the schema](#defining-the-schema)
19
+ - [Types](#types)
20
+ - [Flags](#flags)
21
+ - [Defining default values](#defining-default-values)
22
+ - [Defining custom validators](#defining-custom-validators)
23
+ - [Inspecting the schema](#inspecting-the-schema)
24
+ - [Using the store](#using-the-store)
25
+ - [Putting data in the store](#putting-data-in-the-store)
26
+ - [Updating data](#updating-data)
27
+ - [Unregistered keys are ignored](#unregistered-keys-are-ignored)
28
+ - [Deleting data](#deleting-data)
29
+ - [Fetching data](#fetching-data)
30
+ - [Default values](#default-values)
31
+ - [Inspecting all data](#inspecting-all-data)
32
+ - [Putting it all together: synchronous version](#putting-it-all-together-synchronous-version)
33
+ - [SecurityChecker example: a configurable, low-level component](#securitychecker-example-a-configurable-low-level-component)
34
+ - [DnsQuerier example: a low-level component with post-configuration application operations](#dnsquerier-example-a-low-level-component-with-post-configuration-application-operations)
35
+ - [Downloader example: a high-level component that combines subcomponents](#downloader-example-a-high-level-component-that-combines-subcomponents)
36
+ - [The special problem of conflicting overlapping configuration names and translation](#the-special-problem-of-conflicting-overlapping-configuration-names-and-translation)
37
+ - [Code example](#code-example)
38
+ - [Main function example](#main-function-example)
39
+ - [Putting it all together: asynchronous version](#putting-it-all-together-asynchronous-version)
40
+
41
+ <!-- /MarkdownTOC -->
35
42
 
36
43
  ## Motivations
37
44
 
@@ -109,13 +116,13 @@ There is also `ConfigKit::Store`. This is a class that stores configuration valu
109
116
 
110
117
  ### Translators
111
118
 
112
- And finally there is a "translator" class: `ConfigKit::TableTranslator`. The role of translators are described in the section "The special problem of conflicting overlapping configuration names and translation".
119
+ And finally there are "translator" classes: `ConfigKit::TableTranslator` and `ConfigKit::PrefixTranslator`. The role of translators are described in the section "The special problem of conflicting overlapping configuration names and translation".
113
120
 
114
121
  ## Using the schema
115
122
 
116
123
  ### Defining the schema
117
124
 
118
- Start using ConfigKit by defining a schema. There are two ways to do this. The first one is to simply create ConfigKit::Schema object and adding definitions to it:
125
+ Start using ConfigKit by defining a schema. There are two ways to do this. The first one is to simply create ConfigKit::Schema object and adding definitions to it with `schema.add(name, type, flags, [default value])`:
119
126
 
120
127
  ~~~c++
121
128
  ConfigKit::Schema schema;
@@ -150,7 +157,25 @@ struct YourSchema: public ConfigKit::Schema {
150
157
  YourSchema schema;
151
158
  ~~~
152
159
 
153
- Tip: see ConfigKit/Common.h for all supported types and flags.
160
+ #### Types
161
+
162
+ The following types are available:
163
+
164
+ * `STRING_TYPE` -- a string.
165
+ * `PASSWORD_TYPE` -- a password string. Unlike `STRING_TYPE`, the value of password fields will be filtered out in the output generated by `ConfigKit::Store::inspect()`. Learn more about `inspect()` in [Using the store -- Inspecting all data](#inspecting-all-data).
166
+ * `INT_TYPE` -- a signed integer.
167
+ * `UINT_TYPE` -- an unsigned integer.
168
+ * `FLOAT_TYPE` -- a floating point number.
169
+ * `BOOL_TYPE` -- a boolean.
170
+ * `ARRAY_TYPE` -- an generic array. May contain any values.
171
+ * `STRING_ARRAY_TYPE` -- an array of strings.
172
+
173
+ #### Flags
174
+
175
+ * `REQUIRED` -- this field is required. Mutually exclusive with `OPTIONAL`.
176
+ * `OPTIONAL` -- this field is optional. Mutually exclusive with `REQUIRED`.
177
+ * `CACHE_DEFAULT_VALUE` -- use in combination with [dynamic default values](#defining-default-values). When this flag is set, the value returned by the dynamic value function is cached so that the function won't be called over and over again.
178
+ * `READ_ONLY` -- this field can only be set once. Only the first `ConfigKit::Store::update()` call actually updates the value; subsequent calls won't. Learn more about `update()` in [Using the store -- Putting data in the store](#putting-data-in-the-store).
154
179
 
155
180
  ### Defining default values
156
181
 
@@ -598,7 +623,7 @@ Whenever Downloader is configured, it configures subcomponents too. But whenever
598
623
  There is one special problem that deserves attention: a high-level component may not necessarily want to expose their subcomponents' configuration options using the same names. For example, both `SecurityChecker` and `DnsQuerier` expose a `timeout` option, but they are *different* timeouts, and are even distinct from the Downloader's own download timeout. To solve this special problem of **conflicting overlapping configuration names**, we utilize a **translation system**. We define how the Downloader's configuration keys are to be mapped a specific subcomponent's configuration keys. We obviously can't define the entire mapping, because that would return us to the original problem of having to manually write so much repeated code. There are several ways to deal with this, such as:
599
624
 
600
625
  - Assuming that most options don't have to be renamed, and only define exceptions to this rule. This is the approach that is demonstrated in this example. The `ConfigKit::TableTranslator` class implements this translation strategy.
601
- - Prefixing the subcomponents' options. This approach is left as an exercise to the reader.
626
+ - Prefixing the subcomponents' options. The `ConfigKit::PrefixTranslator` class implements this translation strategy.
602
627
 
603
628
  #### Code example
604
629
 
@@ -37,6 +37,7 @@
37
37
  #include <Exceptions.h>
38
38
  #include <Logging.h>
39
39
  #include <ConfigKit/Common.h>
40
+ #include <ConfigKit/DummyTranslator.h>
40
41
  #include <ConfigKit/Utils.h>
41
42
  #include <DataStructures/StringKeyTable.h>
42
43
  #include <Utils/StrIntUtils.h>
@@ -94,21 +95,6 @@ public:
94
95
  typedef boost::function<void (const Store &store, vector<Error> &errors)> Validator;
95
96
 
96
97
  private:
97
- class DummyTranslator {
98
- public:
99
- StaticString translateOne(const StaticString &key) const {
100
- return key;
101
- }
102
-
103
- StaticString reverseTranslateOne(const StaticString &key) const {
104
- return key;
105
- }
106
-
107
- vector<Error> reverseTranslate(const vector<Error> &errors) const {
108
- return errors;
109
- }
110
- };
111
-
112
98
  StringKeyTable<Entry> entries;
113
99
  boost::container::vector<Validator> validators;
114
100
  bool finalized;
@@ -255,6 +241,7 @@ public:
255
241
 
256
242
  switch (entry->type) {
257
243
  case STRING_TYPE:
244
+ case PASSWORD_TYPE:
258
245
  if (value.isConvertibleTo(Json::stringValue)) {
259
246
  return true;
260
247
  } else {
@@ -294,6 +281,27 @@ public:
294
281
  error = Error("'{{" + key + "}}' must be a boolean");
295
282
  return false;
296
283
  }
284
+ case ARRAY_TYPE:
285
+ if (value.isConvertibleTo(Json::arrayValue)) {
286
+ return true;
287
+ } else {
288
+ error = Error("'{{" + key + "}}' must be an array");
289
+ return false;
290
+ }
291
+ case STRING_ARRAY_TYPE:
292
+ if (value.isConvertibleTo(Json::arrayValue)) {
293
+ Json::Value::const_iterator it, end = value.end();
294
+ for (it = value.begin(); it != end; it++) {
295
+ if (it->type() != Json::stringValue) {
296
+ error = Error("'{{" + key + "}}' may only contain strings");
297
+ return false;
298
+ }
299
+ }
300
+ return true;
301
+ } else {
302
+ error = Error("'{{" + key + "}}' must be an array");
303
+ return false;
304
+ }
297
305
  default:
298
306
  P_BUG("Unknown type " + Passenger::toString((int) entry->type));
299
307
  return false;