Skip to content

Commit

Permalink
Log warnings instead of errors
Browse files Browse the repository at this point in the history
Improve tests
Add GitHub guidelines
  • Loading branch information
youming-lin committed Jul 13, 2017
1 parent bb4e4c0 commit e00973d
Show file tree
Hide file tree
Showing 28 changed files with 149 additions and 90 deletions.
34 changes: 34 additions & 0 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Contributing to IBM-Swift

We welcome contributions, and request you follow these guidelines.

- [Raising issues](#raising-issues)
- [Contributor License Agreement](#contributor-license-agreement)
- [Coding Standards](#coding-standards)


## Raising issues

Please raise any bug reports on the issue tracker. Be sure to
search the list to see if your issue has already been raised.

A good bug report is one that make it easy for us to understand what you were
trying to do and what went wrong. Provide as much context as possible so we can try to recreate the issue.

### Contributor License Agreement

In order for us to accept pull-requests, the contributor must first complete
a Contributor License Agreement (CLA). Please see our [CLA repo](http://github.com/IBM-Swift/CLA) for more information.

This clarifies the intellectual property license granted with any contribution. It is for your protection as a
Contributor as well as the protection of IBM and its customers; it does not
change your rights to use your own Contributions for any other purpose.

### Coding standards

Please ensure you follow [the Kitura coding standards](https://github.com/IBM-Swift/Kitura/blob/master/Documentation/CodeConventions.md)

Please note:

- all files must have the Apache license in the header.
- all PRs must have passing builds for all operating systems.
20 changes: 20 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!--- Provide a general summary of your changes in the Title above -->

## Description
<!--- Describe your changes in detail -->

## Motivation and Context
<!--- Why is this change required? What problem does it solve? -->
<!--- If it fixes an open issue, please link to the issue here. -->

## How Has This Been Tested?
<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, and the tests you ran to -->
<!--- see how your change affects other areas of the code, etc. -->

## Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [ ] I have submitted a [CLA form](https://github.com/IBM-Swift/CLA)
- [ ] If applicable, I have updated the documentation accordingly.
- [ ] If applicable, I have added tests to cover my changes.
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import PackageDescription
let package = Package(
name: "Configuration",
targets: [
Target(name: "TestProgram", dependencies: [ .Target(name: "Configuration") ])
Target(name: "ConfigurationTestExecutable", dependencies: [.Target(name: "Configuration")])
],
dependencies: [
.Package(url: "https://github.com/IBM-Swift/LoggerAPI.git", majorVersion: 1)
Expand Down
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Configuration

[![Build Status - Master](https://api.travis-ci.org/IBM-Swift/Configuration.svg?branch=master)](https://travis-ci.org/IBM-Swift/Configuration)
[![Build Status](https://api.travis-ci.org/IBM-Swift/Configuration.svg?branch=master)](https://travis-ci.org/IBM-Swift/Configuration)
![macOS](https://img.shields.io/badge/os-macOS-green.svg?style=flat)
![Linux](https://img.shields.io/badge/os-linux-green.svg?style=flat)
![Apache 2](https://img.shields.io/badge/license-Apache2-blue.svg?style=flat)
Expand Down Expand Up @@ -34,13 +34,13 @@ manager.load(file: "config.json").load(.environmentVariables)
let value = manager["path:to:configuration:value"]
```

## Loading configuration data
## Loading Configuration Data

`Configuration` has many methods to load configuration data.

**NOTE:** In all cases, configuration key paths are case sensitive.

### From a raw object:
### From a Raw Object:

```swift
manager.load([
Expand All @@ -51,21 +51,21 @@ manager.load([
])
```

### From command line arguments:
### From Command-line Arguments:

```swift
manager.load(.commandLineArguments)
```

To inject configurations via the commandline at runtime, set configuration values when launching the executable, like so:
To inject configurations via the command-line at runtime, set configuration values when launching the executable, like so:

```
./myApp --path.to.configuration=value
```

You can set your preferred argument prefix (`--`) and path separator (`.`) strings when instantiating `ConfigurationManager`.

### From environment variables:
### From Environment Variables:

```swift
manager.load(.environmentVariables)
Expand All @@ -79,14 +79,14 @@ PATH__TO__CONFIGURATION=value

You can set your preferred path separator (default `__`) string when instantiating `ConfigurationManager`.

### From a Data object:
### From a Data Object:

```swift
let data = Data(...)
manager.load(data: data)
```

### From a file:
### From a File:

```swift
manager.load(file: "/path/to/file")
Expand All @@ -111,15 +111,15 @@ manager.load(file: "../path/to/file", relativeFrom: .customPath("/path/to/somewh

**NOTE:** The following `relativeFrom` options, `.executable` (default), `.pwd`, and `.project`, are meant to be used by applications that run from the command-line, and not from within Xcode. This is because the executable and present working directory are different for the application when ran inside Xcode as opposed to when it is ran from the command-line. Under Xcode, this package will change the paths to point to file locations as if the application is running on the command-line.

### From a resource URL:
### From a Resource URL:

```swift
manager.load(url: myURL)
```

**NOTE:** The URL MUST include a scheme, i.e., `file://`, `http://`, etc.

### From multiple sources:
### From Multiple Sources:

You can chain these methods to load configuration data from multiple sources all at once. If the same configuration key exists in the multiple sources, the one most recently loaded will override the ones loaded earlier. In this simple example,

Expand All @@ -131,7 +131,7 @@ the value for `foo` is now `baz` because `["foo": "baz"]` was more recently load

**NOTE:** Currently, `Configuration` only supports JSON and PLIST formats for resources loaded from data, file, or URL. You can write a custom deserializer to parse additional formats.

## Accessing configuration data
## Accessing Configuration Data

To get individual configuration values after they have been loaded, use:

Expand All @@ -155,7 +155,7 @@ The configuration store is represented as a tree, where the path elements in key
}
```

The value is returned as an instance of `Any`. Therefore, it's important to cast the value to the datatype you want to use. For instance:
The value returned is typed as `Any?`. Therefore, it's important to cast the value to the type you want to use. For instance:

```swift
let stringValue = manager["VCAP_SERVICES:cloudantNoSQLDB:0:credentials:host"] as? String
Expand Down
22 changes: 10 additions & 12 deletions Sources/Configuration/ConfigurationManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public class ConfigurationManager {
return self
}

/// Load configurations from command line arguments or environment variables.
/// Load configurations from command-line arguments or environment variables.
/// For command line arguments, the configurations are parsed from arguments
/// in this format: `<keyPrefix><path>=<value>`
///
Expand All @@ -130,7 +130,7 @@ public class ConfigurationManager {
case .commandLineArguments:
let argv = CommandLine.arguments

Log.debug("Loading commandline arguments: \(argv)")
Log.debug("Loading command-line arguments: \(argv)")

// skip first since it's always the executable
for index in 1..<argv.count {
Expand Down Expand Up @@ -167,7 +167,7 @@ public class ConfigurationManager {
/// - Parameter data: The Data object containing configurations.
/// - Parameter deserializerName: Optional. Designated deserializer for the configuration
/// resource. Defaults to `nil`. Pass a value to force the parser to deserialize according to
/// the given format, i.e., `JSONDeserializer.name`; otherwise, parser will go through a list
/// the given format, i.e., `JSONDeserializer.shared.name`; otherwise, parser will go through a list
/// a deserializers and attempt to deserialize using each one.
@discardableResult
public func load(data: Data, deserializerName: String? = nil) -> ConfigurationManager {
Expand All @@ -180,7 +180,7 @@ public class ConfigurationManager {
self.load(try deserializer.deserialize(data: data))
}
catch {
Log.error("Unable to deserialize data using \"\(deserializerName)\" deserializer")
Log.warning("Unable to deserialize data using \"\(deserializerName)\" deserializer")
}

return self
Expand All @@ -196,7 +196,7 @@ public class ConfigurationManager {
}
}

Log.error("Unable to deserialize data using any known deserializer")
Log.warning("Unable to deserialize data using any known deserializer")

return self
}
Expand All @@ -208,7 +208,7 @@ public class ConfigurationManager {
/// - Parameter relativeFrom: Optional. Defaults to the location of the executable.
/// - Parameter deserializerName: Optional. Designated deserializer for the configuration
/// resource. Defaults to `nil`. Pass a value to force the parser to deserialize
/// according to the given format, i.e., `JSONDeserializer.name`; otherwise, parser will
/// according to the given format, i.e., `JSONDeserializer.shared.name`; otherwise, parser will
/// go through a list a deserializers and attempt to deserialize using each one.
@discardableResult
public func load(file: String,
Expand All @@ -232,27 +232,25 @@ public class ConfigurationManager {
pathURL = URL(fileURLWithPath: relativeFrom.path).appendingPathComponent(file).standardized
}

Log.verbose("Loading file: \(pathURL)")

return self.load(url: pathURL, deserializerName: deserializerName)
}

/// Load configurations from a remote location.
/// Load configurations from a URL location.
///
/// - Parameter url: The URL pointing to a configuration resource.
/// - Parameter deserializerName: Optional. Designated deserializer for the configuration
/// resource. Defaults to `nil`. Pass a value to force the parser to deserialize according to
/// the given format, i.e., `JSONDeserializer.name`; otherwise, parser will go through a list
/// the given format, i.e., `JSONDeserializer.shared.name`; otherwise, parser will go through a list
/// a deserializers and attempt to deserialize using each one.
@discardableResult
public func load(url: URL, deserializerName: String? = nil) -> ConfigurationManager {
Log.verbose("Loading URL: \(url)")
Log.verbose("Loading URL: \(url.standardized.path)")

do {
try self.load(data: Data(contentsOf: url), deserializerName: deserializerName)
}
catch {
Log.error("Unable to load data from URL \(url)")
Log.warning("Unable to load data from URL \(url.standardized.path)")
}

return self
Expand Down
File renamed without changes.
25 changes: 16 additions & 9 deletions Tests/ConfigurationTests/ConfigurationManagerTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,26 +61,31 @@ class ConfigurationManagerTest: XCTestCase {

// Helper function to run shell commands
// Tip from http://stackoverflow.com/a/26973384
func shell(_ args: String..., environment: [String: String] = [:]) -> (Pipe, Pipe, Int32) {
func shell(_ args: String...,
currentDirectoryPath: String = presentWorkingDirectory,
environment: [String: String] = [:]) -> (Pipe, Pipe, Int32) {
// Print out the command to be executed
var command = "/usr/bin/env"

args.forEach { command.append(" " + $0) }
print("Executing command: \(String(describing: command))")

#if os(Linux) && !swift(>=3.1)
let process = Task()
#else
let process = Process()
typealias Process = Task
#endif

// Configure the Process instance
let process = Process()
let errPipe = Pipe()
let outPipe = Pipe()
process.launchPath = "/usr/bin/env"
process.arguments = args
process.currentDirectoryPath = currentDirectoryPath
process.environment = environment
process.launchPath = "/usr/bin/env"
process.standardError = errPipe
process.standardOutput = outPipe

// Execute the Process instance
process.launch()
process.waitUntilExit()

Expand Down Expand Up @@ -189,7 +194,7 @@ class ConfigurationManagerTest: XCTestCase {

func testExternalExecutable() {
let projectFolder = URL(fileURLWithPath: #file).appendingPathComponent("../../../").standardized
let testProgramURL = projectFolder.appendingPathComponent(".build/debug/TestProgram").standardized
let testProgramURL = projectFolder.appendingPathComponent(".build/debug/ConfigurationTestExecutable").standardized

var (errPipe, outPipe, exitCode): (Pipe, Pipe, Int32)
var output: String?, error: String?
Expand All @@ -208,14 +213,16 @@ class ConfigurationManagerTest: XCTestCase {
// Need to pass in current environment variables on local machine or it will fail with
// `error: Unable to find executable for 'xcrun'`
// when ran with Xcode 9 beta
(errPipe, outPipe, exitCode) = shell("swift", "build", "-C", projectFolder.path, environment: ProcessInfo.processInfo.environment)
(errPipe, outPipe, exitCode) = shell("swift", "build",
currentDirectoryPath: projectFolder.path,
environment: ProcessInfo.processInfo.environment)
output = String(data: outPipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8)

print(output ?? "No stdout from `swift build -C \(projectFolder.path)`")
print(output ?? "No stdout from `swift build`")

guard exitCode == 0 else {
let error = String(data: errPipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8)
XCTFail(error ?? "No stderr from `swift build -C \(projectFolder.path)`")
XCTFail(error ?? "No stderr from `swift build`")
return
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion docs/Classes.html
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ <h4>Declaration</h4>
</article>
</div>
<section class="footer">
<p>&copy; 2017 <a class="link" href="" target="_blank" rel="external">IBM</a>. All rights reserved. (Last updated: 2017-05-25)</p>
<p>&copy; 2017 <a class="link" href="" target="_blank" rel="external">IBM</a>. All rights reserved. (Last updated: 2017-07-13)</p>
<p>Generated by <a class="link" href="https://github.com/realm/jazzy" target="_blank" rel="external">jazzy ♪♫ v0.8.1</a>, a <a class="link" href="http://realm.io" target="_blank" rel="external">Realm</a> project.</p>
</section>
</body>
Expand Down
12 changes: 6 additions & 6 deletions docs/Classes/ConfigurationManager.html
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ <h4>Parameters</h4>
<section class="section">
<div class="pointer"></div>
<div class="abstract">
<p>Load configurations from command line arguments or environment variables.
<p>Load configurations from command-line arguments or environment variables.
For command line arguments, the configurations are parsed from arguments
in this format: <code>&lt;keyPrefix&gt;&lt;path&gt;=&lt;value&gt;</code></p>

Expand Down Expand Up @@ -549,7 +549,7 @@ <h4>Parameters</h4>
<div>
<p>Optional. Designated deserializer for the configuration
resource. Defaults to <code>nil</code>. Pass a value to force the parser to deserialize according to
the given format, i.e., <code>JSONDeserializer.name</code>; otherwise, parser will go through a list
the given format, i.e., <code>JSONDeserializer.shared.name</code>; otherwise, parser will go through a list
a deserializers and attempt to deserialize using each one.</p>
</div>
</td>
Expand Down Expand Up @@ -624,7 +624,7 @@ <h4>Parameters</h4>
<div>
<p>Optional. Designated deserializer for the configuration
resource. Defaults to <code>nil</code>. Pass a value to force the parser to deserialize
according to the given format, i.e., <code>JSONDeserializer.name</code>; otherwise, parser will
according to the given format, i.e., <code>JSONDeserializer.shared.name</code>; otherwise, parser will
go through a list a deserializers and attempt to deserialize using each one.</p>
</div>
</td>
Expand All @@ -648,7 +648,7 @@ <h4>Parameters</h4>
<section class="section">
<div class="pointer"></div>
<div class="abstract">
<p>Load configurations from a remote location.</p>
<p>Load configurations from a URL location.</p>

</div>
<div class="declaration">
Expand Down Expand Up @@ -685,7 +685,7 @@ <h4>Parameters</h4>
<div>
<p>Optional. Designated deserializer for the configuration
resource. Defaults to <code>nil</code>. Pass a value to force the parser to deserialize according to
the given format, i.e., <code>JSONDeserializer.name</code>; otherwise, parser will go through a list
the given format, i.e., <code>JSONDeserializer.shared.name</code>; otherwise, parser will go through a list
a deserializers and attempt to deserialize using each one.</p>
</div>
</td>
Expand Down Expand Up @@ -777,7 +777,7 @@ <h4>Declaration</h4>
</article>
</div>
<section class="footer">
<p>&copy; 2017 <a class="link" href="" target="_blank" rel="external">IBM</a>. All rights reserved. (Last updated: 2017-05-25)</p>
<p>&copy; 2017 <a class="link" href="" target="_blank" rel="external">IBM</a>. All rights reserved. (Last updated: 2017-07-13)</p>
<p>Generated by <a class="link" href="https://github.com/realm/jazzy" target="_blank" rel="external">jazzy ♪♫ v0.8.1</a>, a <a class="link" href="http://realm.io" target="_blank" rel="external">Realm</a> project.</p>
</section>
</body>
Expand Down
2 changes: 1 addition & 1 deletion docs/Classes/ConfigurationManager/BasePath.html
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ <h4>Declaration</h4>
</article>
</div>
<section class="footer">
<p>&copy; 2017 <a class="link" href="" target="_blank" rel="external">IBM</a>. All rights reserved. (Last updated: 2017-05-25)</p>
<p>&copy; 2017 <a class="link" href="" target="_blank" rel="external">IBM</a>. All rights reserved. (Last updated: 2017-07-13)</p>
<p>Generated by <a class="link" href="https://github.com/realm/jazzy" target="_blank" rel="external">jazzy ♪♫ v0.8.1</a>, a <a class="link" href="http://realm.io" target="_blank" rel="external">Realm</a> project.</p>
</section>
</body>
Expand Down
2 changes: 1 addition & 1 deletion docs/Classes/ConfigurationManager/Source.html
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ <h4>Declaration</h4>
</article>
</div>
<section class="footer">
<p>&copy; 2017 <a class="link" href="" target="_blank" rel="external">IBM</a>. All rights reserved. (Last updated: 2017-05-25)</p>
<p>&copy; 2017 <a class="link" href="" target="_blank" rel="external">IBM</a>. All rights reserved. (Last updated: 2017-07-13)</p>
<p>Generated by <a class="link" href="https://github.com/realm/jazzy" target="_blank" rel="external">jazzy ♪♫ v0.8.1</a>, a <a class="link" href="http://realm.io" target="_blank" rel="external">Realm</a> project.</p>
</section>
</body>
Expand Down
Loading

0 comments on commit e00973d

Please sign in to comment.