Make the remote features optional
diff --git a/viper.go b/viper.go
index 11f3a77..799983f 100644
--- a/viper.go
+++ b/viper.go
@@ -35,7 +35,6 @@
 	"github.com/spf13/cast"
 	jww "github.com/spf13/jwalterweatherman"
 	"github.com/spf13/pflag"
-	crypt "github.com/xordataexchange/crypt/config"
 )
 
 var v *Viper
@@ -44,6 +43,14 @@
 	v = New()
 }
 
+type remoteConfigFactory interface {
+	Get(rp RemoteProvider) (io.Reader, error)
+	Watch(rp RemoteProvider) (io.Reader, error)
+}
+
+// RemoteConfig is optional, see the remote package
+var RemoteConfig remoteConfigFactory
+
 // Denotes encountering an unsupported
 // configuration filetype.
 type UnsupportedConfigError string
@@ -115,7 +122,7 @@
 	configPaths []string
 
 	// A set of remote providers to search for the configuration
-	remoteProviders []*remoteProvider
+	remoteProviders []*defaultRemoteProvider
 
 	// Name of file to look for inside the path
 	configName string
@@ -160,17 +167,40 @@
 	SupportedRemoteProviders = []string{"etcd", "consul"}
 }
 
-// remoteProvider stores the configuration necessary
-// to connect to a remote key/value store.
-// Optional secretKeyring to unencrypt encrypted values
-// can be provided.
-type remoteProvider struct {
+type defaultRemoteProvider struct {
 	provider      string
 	endpoint      string
 	path          string
 	secretKeyring string
 }
 
+func (rp defaultRemoteProvider) Provider() string {
+	return rp.provider
+}
+
+func (rp defaultRemoteProvider) Endpoint() string {
+	return rp.endpoint
+}
+
+func (rp defaultRemoteProvider) Path() string {
+	return rp.path
+}
+
+func (rp defaultRemoteProvider) SecretKeyring() string {
+	return rp.secretKeyring
+}
+
+// RemoteProvider stores the configuration necessary
+// to connect to a remote key/value store.
+// Optional secretKeyring to unencrypt encrypted values
+// can be provided.
+type RemoteProvider interface {
+	Provider() string
+	Endpoint() string
+	Path() string
+	SecretKeyring() string
+}
+
 // Universally supported extensions.
 var SupportedExts []string = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop"}
 
@@ -252,7 +282,7 @@
 	}
 	if provider != "" && endpoint != "" {
 		jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint)
-		rp := &remoteProvider{
+		rp := &defaultRemoteProvider{
 			endpoint: endpoint,
 			provider: provider,
 			path:     path,
@@ -284,7 +314,7 @@
 	}
 	if provider != "" && endpoint != "" {
 		jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint)
-		rp := &remoteProvider{
+		rp := &defaultRemoteProvider{
 			endpoint: endpoint,
 			provider: provider,
 			path:     path,
@@ -296,7 +326,7 @@
 	return nil
 }
 
-func (v *Viper) providerPathExists(p *remoteProvider) bool {
+func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool {
 	for _, y := range v.remoteProviders {
 		if reflect.DeepEqual(y, p) {
 			return true
@@ -759,6 +789,10 @@
 
 // retrieve the first found remote configuration
 func (v *Viper) getKeyValueConfig() error {
+	if RemoteConfig == nil {
+		return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'")
+	}
+
 	for _, rp := range v.remoteProviders {
 		val, err := v.getRemoteConfig(rp)
 		if err != nil {
@@ -770,36 +804,12 @@
 	return RemoteConfigError("No Files Found")
 }
 
-func (v *Viper) getRemoteConfig(provider *remoteProvider) (map[string]interface{}, error) {
-	var cm crypt.ConfigManager
-	var err error
+func (v *Viper) getRemoteConfig(provider *defaultRemoteProvider) (map[string]interface{}, error) {
 
-	if provider.secretKeyring != "" {
-		kr, err := os.Open(provider.secretKeyring)
-		defer kr.Close()
-		if err != nil {
-			return nil, err
-		}
-		if provider.provider == "etcd" {
-			cm, err = crypt.NewEtcdConfigManager([]string{provider.endpoint}, kr)
-		} else {
-			cm, err = crypt.NewConsulConfigManager([]string{provider.endpoint}, kr)
-		}
-	} else {
-		if provider.provider == "etcd" {
-			cm, err = crypt.NewStandardEtcdConfigManager([]string{provider.endpoint})
-		} else {
-			cm, err = crypt.NewStandardConsulConfigManager([]string{provider.endpoint})
-		}
-	}
+	reader, err := RemoteConfig.Get(provider)
 	if err != nil {
 		return nil, err
 	}
-	b, err := cm.Get(provider.path)
-	if err != nil {
-		return nil, err
-	}
-	reader := bytes.NewReader(b)
 	v.marshalReader(reader, v.kvstore)
 	return v.kvstore, err
 }
@@ -817,39 +827,11 @@
 	return RemoteConfigError("No Files Found")
 }
 
-func (v *Viper) watchRemoteConfig(provider *remoteProvider) (map[string]interface{}, error) {
-	var cm crypt.ConfigManager
-	var err error
-
-	if provider.secretKeyring != "" {
-		kr, err := os.Open(provider.secretKeyring)
-		defer kr.Close()
-		if err != nil {
-			return nil, err
-		}
-		if provider.provider == "etcd" {
-			cm, err = crypt.NewEtcdConfigManager([]string{provider.endpoint}, kr)
-		} else {
-			cm, err = crypt.NewConsulConfigManager([]string{provider.endpoint}, kr)
-		}
-	} else {
-		if provider.provider == "etcd" {
-			cm, err = crypt.NewStandardEtcdConfigManager([]string{provider.endpoint})
-		} else {
-			cm, err = crypt.NewStandardConsulConfigManager([]string{provider.endpoint})
-		}
-	}
+func (v *Viper) watchRemoteConfig(provider *defaultRemoteProvider) (map[string]interface{}, error) {
+	reader, err := RemoteConfig.Watch(provider)
 	if err != nil {
 		return nil, err
 	}
-	resp := <-cm.Watch(provider.path, nil)
-	// b, err := cm.Watch(provider.path, nil)
-	err = resp.Error
-	if err != nil {
-		return nil, err
-	}
-
-	reader := bytes.NewReader(resp.Value)
 	v.marshalReader(reader, v.kvstore)
 	return v.kvstore, err
 }