diff --git a/discovery/discovery.go b/discovery/discovery.go new file mode 100644 index 0000000..e804e2a --- /dev/null +++ b/discovery/discovery.go @@ -0,0 +1,47 @@ +package discovery + +import ( + "net/url" + "os" +) + +var Default = NewService() + +type Provider interface { + Discover(serviceUrn string) (*url.URL, error) +} + +type Service struct { + token string + providers []Provider +} + +func (s *Service) Discover(serviceUrn string) (*url.URL, error) { + for idx := range s.providers { + provider := s.providers[idx] + u, err := provider.Discover(serviceUrn) + if err == nil { + return u, nil + } + } + + return nil, os.ErrNotExist +} + +func (s *Service) WithToken(token string) *Service { + s.token = token + return s +} + +func (s *Service) WithProvider(provider Provider) *Service { + s.providers = append(s.providers, provider) + return s +} + +func NewService() *Service { + return &Service{ + providers: []Provider{ + NewLocalDiscovery(), + }, + } +} diff --git a/discovery/discovery.json b/discovery/discovery.json new file mode 100644 index 0000000..971ceda --- /dev/null +++ b/discovery/discovery.json @@ -0,0 +1,3 @@ +{ + "test.service": "http://user:password@localhost:8888/test/path" +} \ No newline at end of file diff --git a/discovery/discovery_test.go b/discovery/discovery_test.go new file mode 100644 index 0000000..91d15f7 --- /dev/null +++ b/discovery/discovery_test.go @@ -0,0 +1,23 @@ +package discovery + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestDiscovery(t *testing.T) { + discovery := NewService() + + url, err := discovery.Discover("unknown.service") + assert.Error(t, err) + assert.Nil(t, url) + + url, err = discovery.Discover("test.service") + assert.NoError(t, err) + require.NotNil(t, url) + assert.Equal(t, "localhost", url.Hostname()) + assert.Equal(t, "8888", url.Port()) + assert.Equal(t, "/test/path", url.Path) +} diff --git a/discovery/file.go b/discovery/file.go new file mode 100644 index 0000000..38da213 --- /dev/null +++ b/discovery/file.go @@ -0,0 +1,58 @@ +package discovery + +import ( + "net/url" + "os" + "path" + + "git.twelvetwelve.org/library/core/json" +) + +type LocalDiscovery struct { +} + +func lookup(kv map[string]string, serviceUrn string) *url.URL { + rawURL, ok := kv[serviceUrn] + if !ok { + return nil + } + + u, err := url.Parse(rawURL) + if err != nil { + return nil + } + return u +} + +func lookupFrom(path string, serviceUrn string) *url.URL { + services := make(map[string]string) + err := json.ReadFromFile(path, &services) + if err != nil { + return nil + } + return lookup(services, serviceUrn) +} + +func (ld *LocalDiscovery) Discover(serviceUrn string) (*url.URL, error) { + if url := lookupFrom("discovery.json", serviceUrn); url != nil { + return url, nil + } + + home, err := os.UserHomeDir() + if err != nil { + homeConf := path.Join(home, ".config", "discovery.json") + if url := lookupFrom(homeConf, serviceUrn); url != nil { + return url, nil + } + } + + if url := lookupFrom("/etc/discovery/discovery.json", serviceUrn); url != nil { + return url, nil + } + + return nil, os.ErrNotExist +} + +func NewLocalDiscovery() *LocalDiscovery { + return &LocalDiscovery{} +}