Skip to content

Commit

Permalink
Add configuration file.
Browse files Browse the repository at this point in the history
This is based on Jacek Izykowski's work:
#21

Initial patchset is a merge of his work to master. Following patchsets are fixes and
improvements.

Changes:
* Remove loading keystone variables from environment.
* Introduce an ini-format config file.
* Command line params take precedence over config params.
* Move flags to configuration/ package.
* Refactors.
* Introduce dryRun flag that parses config but doesn't do anything.
* Bake sample test config file into test binary using go generate. This
is done so that we don't have to complicate integration test setup on
CI-side and needlessly couple it. It will be easier to add test cases
this way as well.

Co-authored-by: Jacek Izykowski <jacek.izykowski@codilime.com>
Co-authored-by: Michal Kostrzewa <michal.kostrzewa@codilime.com>

Change-Id: I92f0df4f84f519836a0af183cc4580f72189feb0
Closes-Bug: #1787565
  • Loading branch information
Michal Kostrzewa committed Sep 11, 2018
1 parent adf6312 commit 33bf8bd
Show file tree
Hide file tree
Showing 18 changed files with 518 additions and 140 deletions.
3 changes: 3 additions & 0 deletions .gitignore
@@ -1,6 +1,9 @@
# build output dir
build/*

# files generated with go generate
baked*

# test reports
*.xml

Expand Down
8 changes: 7 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Invoke-Build.ps1
Expand Up @@ -34,8 +34,9 @@ if (-not $SkipExe) {

if (-not $SkipTests) {
Write-Host "** Building tests..."
ginkgo build -r -tags "unit integration" .
./Scripts/New-BakedTestData.ps1

ginkgo build -r -tags "unit integration" .
if ($LastExitCode -ne 0) {
throw "Build failed."
}
Expand Down
2 changes: 2 additions & 0 deletions Invoke-Tests.ps1
Expand Up @@ -15,6 +15,8 @@
#
param([switch] $RunIntegrationTests)

./Scripts/New-BakedTestData.ps1

Write-Host "Running docker driver unit tests..."
go test -coverpkg=./... -covermode count -coverprofile="cover_unit.out" -tags unit . -- ginkgo.trace

Expand Down
20 changes: 20 additions & 0 deletions Scripts/New-BakedTestData.ps1
@@ -0,0 +1,20 @@
#
# Copyright (c) 2018 Juniper Networks, Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the `"License`");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an `"AS IS`" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
Write-Host "Baking test case data..."
go generate -tags "unit, integration" ./...
if ($LastExitCode -ne 0) {
throw "Code generation failed."
}
18 changes: 17 additions & 1 deletion Scripts/Update-LicenseFiles.ps1
@@ -1,5 +1,21 @@
#
# Looks for license files in vendor/ directory and generates two files:
# Copyright (c) 2018 Juniper Networks, Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the `"License`");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an `"AS IS`" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#

# Script looks for license files in vendor/ directory and generates two files:
# - Attributions.txt
# - LICENSE_MSI.txt
#
Expand Down
29 changes: 1 addition & 28 deletions adapters/secondary/controller_rest/auth/keystone.go
Expand Up @@ -17,11 +17,8 @@ package auth

import (
"errors"
"os"
"reflect"

contrail "github.com/Juniper/contrail-go-api"
log "github.com/sirupsen/logrus"
)

type KeystoneParams struct {
Expand All @@ -32,7 +29,7 @@ type KeystoneParams struct {
Os_token string
}

func NewKeystoneAuth(keys *KeystoneParams) (*contrail.KeepaliveKeystoneClient, error) {
func NewKeystoneAuth(keys KeystoneParams) (*contrail.KeepaliveKeystoneClient, error) {
if keys.Os_auth_url == "" {
// this corner case is not handled by keystone.Authenticate. Causes panic.
return nil, errors.New("Empty Keystone auth URL")
Expand All @@ -42,27 +39,3 @@ func NewKeystoneAuth(keys *KeystoneParams) (*contrail.KeepaliveKeystoneClient, e
keys.Os_username, keys.Os_password, keys.Os_token)
return keystone, nil
}

func (k *KeystoneParams) LoadFromEnvironment() {

k.Os_auth_url = getenvIfNil(k.Os_auth_url, "OS_AUTH_URL")
k.Os_username = getenvIfNil(k.Os_username, "OS_USERNAME")
k.Os_tenant_name = getenvIfNil(k.Os_tenant_name, "OS_TENANT_NAME")
k.Os_password = getenvIfNil(k.Os_password, "OS_PASSWORD")
k.Os_token = getenvIfNil(k.Os_token, "OS_TOKEN")

// print a warning for every empty variable
keysReflection := reflect.ValueOf(*k)
for i := 0; i < keysReflection.NumField(); i++ {
if keysReflection.Field(i).String() == "" {
log.Warn("Keystone variable empty: ", keysReflection.Type().Field(i).Name)
}
}
}

func getenvIfNil(currentVal, envVar string) string {
if currentVal == "" {
return os.Getenv(envVar)
}
return currentVal
}
51 changes: 1 addition & 50 deletions adapters/secondary/controller_rest/auth/keystone_test.go
Expand Up @@ -18,7 +18,6 @@
package auth_test

import (
"os"
"testing"

"github.com/Juniper/contrail-windows-docker-driver/adapters/secondary/controller_rest/auth"
Expand All @@ -33,54 +32,6 @@ func TestKeystone(t *testing.T) {
}

var _ = Describe("Keystone", func() {
Context("KeystoneParams", func() {
type TestCase struct {
keys auth.KeystoneParams
expectedKeys auth.KeystoneParams
}
DescribeTable("LoadFromEnvironment loads empty fields from env",
func(t TestCase) {
os.Setenv("OS_AUTH_URL", "http://1.3.3.7:5000/v2.0")
os.Setenv("OS_USERNAME", "env_username")
os.Setenv("OS_TENANT_NAME", "env_tenant")
os.Setenv("OS_PASSWORD", "okon")
t.keys.LoadFromEnvironment()
Expect(t.keys).To(BeEquivalentTo(t.expectedKeys))
},
Entry("variables present", TestCase{
keys: auth.KeystoneParams{
Os_auth_url: "http://1.2.3.4:5000/v2.0",
Os_username: "admin",
Os_tenant_name: "admin",
Os_password: "hunter2",
Os_token: "",
},
expectedKeys: auth.KeystoneParams{
Os_auth_url: "http://1.2.3.4:5000/v2.0",
Os_username: "admin",
Os_tenant_name: "admin",
Os_password: "hunter2",
Os_token: "",
},
}),
Entry("variables empty (but are present in envs)", TestCase{
keys: auth.KeystoneParams{
Os_auth_url: "",
Os_username: "",
Os_tenant_name: "",
Os_password: "",
Os_token: "",
},
expectedKeys: auth.KeystoneParams{
Os_auth_url: "http://1.3.3.7:5000/v2.0",
Os_username: "env_username",
Os_tenant_name: "env_tenant",
Os_password: "okon",
Os_token: "",
},
}),
)
})

Context("NewKeystoneAuth", func() {
type TestCase struct {
Expand All @@ -89,7 +40,7 @@ var _ = Describe("Keystone", func() {
}
DescribeTable("NewKeystoneAuth",
func(t TestCase) {
_, err := auth.NewKeystoneAuth(&t.keys)
_, err := auth.NewKeystoneAuth(t.keys)
if t.shouldErr {
Expect(err).To(HaveOccurred())
} else {
Expand Down
2 changes: 1 addition & 1 deletion adapters/secondary/controller_rest/factory.go
Expand Up @@ -21,7 +21,7 @@ import (
"github.com/Juniper/contrail-windows-docker-driver/adapters/secondary/controller_rest/auth"
)

func NewControllerWithKeystoneAdapter(keys *auth.KeystoneParams, apiClient *contrail.Client) (*ControllerAdapter, error) {
func NewControllerWithKeystoneAdapter(keys auth.KeystoneParams, apiClient *contrail.Client) (*ControllerAdapter, error) {
auth, err := auth.NewKeystoneAuth(keys)
if err != nil {
return nil, err
Expand Down
41 changes: 41 additions & 0 deletions cnm-driver.conf.sample
@@ -0,0 +1,41 @@
[DRIVER]
# Net adapter for HNS switch, must be physical
Adapter = Ethernet0

# IP address of Contrail Controller API
ControllerIP = 10.0.0.10

# Port of Contrail Controller API
ControllerPort = 8082

# URL of Agent API
AgentURL = http://127.0.0.1:9091

# Name of Transparent virtual switch.
# Special wildcard "<adapter>" will be interpretted as value of netAdapter
# parameter. For example, if netAdapter is "Ethernet0", then vswitchName will
# be equal to "Layered Ethernet0".
# You can use Get-VMSwitch PowerShell command to check how the switch is called
# on your version of OS.
VSwitchName = Layered?<adapter>


[AUTH]
# Auth method. Available values: (keystone|noauth). If keystone. [KEYSTONE] section must be filled.
AuthMethod = keystone

[KEYSTONE]
# Keystone auth url. If empty, will read from environment variable.
Os_auth_url = http://10.0.0.10:5000/v2.0/

# Contrail username. If empty, will read from environment variable.
Os_username = admin

# Tenant name. If empty, will read environment variable.
Os_tenant_name = admin

# Contrail password. If empty, will read environment variable.
Os_password = hunter2

# Keystone token. If empty, will read environment variable.
Os_token =
33 changes: 33 additions & 0 deletions configuration/New-BakedTestConfigFile.ps1
@@ -0,0 +1,33 @@
#
# Copyright (c) 2018 Juniper Networks, Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the `"License`");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an `"AS IS`" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# This script is invoked by go generate.
# We bake sample configuration file into the compiled test binary, so that we don't have to
# transfer the file separately to remote machine to invoke integration tests that use it.

$CfgFile = Get-Content -Raw ../cnm-driver.conf.sample

"
package configuration_test
const (
sampleCfgFile = ``
$CfgFile
``
)
" | Out-File baked_data_test.go -Encoding ASCII
# We set encoding to ASCII, because without it, we get 'unexpected NUL in input' error while
# compiling the generated file.
6 changes: 6 additions & 0 deletions configuration/README.md
@@ -0,0 +1,6 @@
These tests require, that sample config file in the root of this repository is baked
into the binary itself. Supplied `Invoke-Build.ps1` and `Invoke-Tests.ps1` scripts already
generate the required code. To do this by hand, however, invoke
```
go generate -tags unit,integration ./...
```
65 changes: 65 additions & 0 deletions configuration/configuration.go
@@ -0,0 +1,65 @@
//
// Copyright (c) 2018 Juniper Networks, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package configuration

import (
"github.com/Juniper/contrail-windows-docker-driver/adapters/secondary/controller_rest/auth"
)

type DriverConf struct {
Adapter string
ControllerIP string
ControllerPort int
AgentURL string
VSwitchName string
}

type AuthConf struct {
AuthMethod string
Keystone auth.KeystoneParams
}

type Configuration struct {
Driver DriverConf
Auth AuthConf
}

func NewDefaultConfiguration() (conf Configuration) {
conf.Driver.Adapter = "Ethernet0"
conf.Driver.ControllerIP = "192.168.0.10"
conf.Driver.ControllerPort = 8082
conf.Driver.AgentURL = "http://127.0.0.1:9091"
conf.Driver.VSwitchName = "Layered <adapter>"

conf.Auth.AuthMethod = "noauth"

conf.Auth.Keystone.Os_auth_url = ""
conf.Auth.Keystone.Os_username = ""
conf.Auth.Keystone.Os_tenant_name = ""
conf.Auth.Keystone.Os_password = ""
conf.Auth.Keystone.Os_token = ""

return
}

func DefaultConfigFilepath() string {
return ""
// TODO: uncomment the following lines once templating logic is implemented in ansible.
// For now, return empty string, so that docker driver defaults to reading only command
// line parameters.
// return string(filepath.Join(os.Getenv("ProgramData"),
// "Contrail", "etc", "contrail", "cnm-driver.conf"))
}

0 comments on commit 33bf8bd

Please sign in to comment.