allow lowercase env vars to be read (#21)

diff --git a/config/config.go b/config/config.go
index d7df182..3caf1a3 100644
--- a/config/config.go
+++ b/config/config.go
@@ -63,45 +63,61 @@
 func (c *ConfigMgr) Get(key string) interface{} {
 	c.Lock()
 	defer c.Unlock()
+	allowLowercaseEnv(key)
 	return c.vcfg.Get(key)
 }
 
 func (c *ConfigMgr) GetBool(key string) bool {
 	c.Lock()
 	defer c.Unlock()
+	allowLowercaseEnv(key)
 	return c.vcfg.GetBool(key)
 }
 
 func (c *ConfigMgr) GetFloat64(key string) float64 {
 	c.Lock()
 	defer c.Unlock()
+	allowLowercaseEnv(key)
 	return c.vcfg.GetFloat64(key)
 }
 
 func (c *ConfigMgr) GetInt(key string) int {
 	c.Lock()
 	defer c.Unlock()
+	allowLowercaseEnv(key)
 	return c.vcfg.GetInt(key)
 }
 
 func (c *ConfigMgr) GetString(key string) string {
 	cfg.Lock()
 	defer cfg.Unlock()
+	allowLowercaseEnv(key)
 	return c.vcfg.GetString(key)
 }
 
 func (c *ConfigMgr) GetDuration(key string) time.Duration {
 	cfg.Lock()
 	defer cfg.Unlock()
+	allowLowercaseEnv(key)
 	return c.vcfg.GetDuration(key)
 }
 
 func (c *ConfigMgr) IsSet(key string) bool {
 	c.Lock()
 	defer c.Unlock()
+	allowLowercaseEnv(key)
 	return c.vcfg.IsSet(key)
 }
 
+// hack to allow lowercase env vars to be read by Viper AutomaticEnv()
+func allowLowercaseEnv(key string) {
+	envKey := "apid_" + key
+	if os.Getenv(envKey) != "" {
+		kUpper := "APID_" + strings.ToUpper(key)
+		os.Setenv(kUpper, os.Getenv(envKey))
+	}
+}
+
 func GetConfig() apid.ConfigService {
 	configlock.Lock()
 	defer configlock.Unlock()
diff --git a/config/config_suite_test.go b/config/config_suite_test.go
new file mode 100644
index 0000000..347039e
--- /dev/null
+++ b/config/config_suite_test.go
@@ -0,0 +1,35 @@
+// Copyright 2017 Google Inc.
+//
+// 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 config_test
+
+import (
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+
+	"testing"
+	"github.com/apid/apid-core"
+	"github.com/apid/apid-core/factory"
+)
+
+var _ = BeforeSuite(func() {
+	apid.Initialize(factory.DefaultServicesFactory())
+	apid.Config().SetDefault("test", "test")
+})
+
+
+func TestEvents(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "Config Suite")
+}
diff --git a/config/config_test.go b/config/config_test.go
new file mode 100644
index 0000000..ea43766
--- /dev/null
+++ b/config/config_test.go
@@ -0,0 +1,68 @@
+// Copyright 2017 Google Inc.
+//
+// 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 config_test
+
+import (
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+	"os"
+	"github.com/apid/apid-core"
+	"time"
+)
+
+var _ = Describe("Config Service", func() {
+
+	Context("lowercase env var", func() {
+
+		It("no env var", func() {
+			Expect(apid.Config().Get("test")).To(Equal("test"))
+		})
+
+		It("as interface", func() {
+			os.Setenv("apid_test", "TEST")
+			Expect(apid.Config().Get("test")).To(Equal("TEST"))
+		})
+
+		It("as bool", func() {
+			os.Setenv("apid_test", "true")
+			Expect(apid.Config().GetBool("test")).To(BeTrue())
+		})
+
+		It("as float", func() {
+			os.Setenv("apid_test", "64.1")
+			Expect(apid.Config().GetFloat64("test")).To(Equal(64.1))
+		})
+
+		It("as int", func() {
+			os.Setenv("apid_test", "64")
+			Expect(apid.Config().GetInt("test")).To(Equal(64))
+		})
+
+		It("as string", func() {
+			os.Setenv("apid_test", "TEST")
+			Expect(apid.Config().GetString("test")).To(Equal("TEST"))
+		})
+
+		It("as duration", func() {
+			os.Setenv("apid_test", "300ms")
+			Expect(apid.Config().GetDuration("test")).To(Equal(300 * time.Millisecond))
+		})
+
+		It("as IsSet", func() {
+			os.Setenv("apid_test", "300ms")
+			Expect(apid.Config().IsSet("test")).To(BeTrue())
+		})
+	})
+})