initial commit

This commit is contained in:
Eric Chiang
2016-07-25 13:00:28 -07:00
commit cab271f304
1438 changed files with 335968 additions and 0 deletions

126
cmd/poke/config.go Normal file
View File

@@ -0,0 +1,126 @@
package main
import (
"fmt"
"github.com/coreos/poke/connector"
"github.com/coreos/poke/connector/github"
"github.com/coreos/poke/connector/ldap"
"github.com/coreos/poke/connector/mock"
"github.com/coreos/poke/storage"
"github.com/coreos/poke/storage/kubernetes"
)
// Config is the config format for the main application.
type Config struct {
Issuer string `yaml:"issuer"`
Storage Storage `yaml:"storage"`
Connectors []Connector `yaml:"connectors"`
Web Web `yaml:"web"`
}
// Web is the config format for the HTTP server.
type Web struct {
HTTP string `yaml:"http"`
HTTPS string `yaml:"https"`
TLSCert string `yaml:"tlsCert"`
TLSKey string `yaml:"tlsKey"`
}
// Storage holds app's storage configuration.
type Storage struct {
Type string `yaml:"type"`
Config StorageConfig `yaml:"config"`
}
// UnmarshalYAML allows Storage to unmarshal its config field dynamically
// depending on the type of storage.
func (s *Storage) UnmarshalYAML(unmarshal func(interface{}) error) error {
var storageMeta struct {
Type string `yaml:"type"`
}
if err := unmarshal(&storageMeta); err != nil {
return err
}
s.Type = storageMeta.Type
var c struct {
Config StorageConfig `yaml:"config"`
}
switch storageMeta.Type {
case "kubernetes":
c.Config = &kubernetes.Config{}
default:
return fmt.Errorf("unknown storage type %q", storageMeta.Type)
}
if err := unmarshal(c); err != nil {
return err
}
s.Config = c.Config
return nil
}
// StorageConfig is a configuration that can create a storage.
type StorageConfig interface {
Open() (storage.Storage, error)
}
// Connector is a magical type that can unmarshal YAML dynamically. The
// Type field determines the connector type, which is then customized for Config.
type Connector struct {
Type string `yaml:"type"`
Name string `yaml:"name"`
ID string `yaml:"id"`
Config ConnectorConfig `yaml:"config"`
}
// ConnectorConfig is a configuration that can open a connector.
type ConnectorConfig interface {
Open() (connector.Connector, error)
}
// UnmarshalYAML allows Connector to unmarshal its config field dynamically
// depending on the type of connector.
func (c *Connector) UnmarshalYAML(unmarshal func(interface{}) error) error {
var connectorMetadata struct {
Type string `yaml:"type"`
Name string `yaml:"name"`
ID string `yaml:"id"`
}
if err := unmarshal(&connectorMetadata); err != nil {
return err
}
c.Type = connectorMetadata.Type
c.Name = connectorMetadata.Name
c.ID = connectorMetadata.ID
switch c.Type {
case "mock":
var config struct {
Config mock.Config `yaml:"config"`
}
if err := unmarshal(&config); err != nil {
return err
}
c.Config = &config.Config
case "ldap":
var config struct {
Config ldap.Config `yaml:"config"`
}
if err := unmarshal(&config); err != nil {
return err
}
c.Config = &config.Config
case "github":
var config struct {
Config github.Config `yaml:"config"`
}
if err := unmarshal(&config); err != nil {
return err
}
c.Config = &config.Config
default:
return fmt.Errorf("unknown connector type %q", c.Type)
}
return nil
}

1
cmd/poke/init.go Normal file
View File

@@ -0,0 +1 @@
package main

28
cmd/poke/poke.go Normal file
View File

@@ -0,0 +1,28 @@
package main
import (
"fmt"
"os"
"github.com/spf13/cobra"
)
func commandRoot() *cobra.Command {
rootCmd := &cobra.Command{
Use: "poke",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
os.Exit(2)
},
}
rootCmd.AddCommand(commandServe())
rootCmd.AddCommand(commandVersion())
return rootCmd
}
func main() {
if err := commandRoot().Execute(); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(2)
}
}

111
cmd/poke/serve.go Normal file
View File

@@ -0,0 +1,111 @@
package main
import (
"errors"
"fmt"
"io/ioutil"
"log"
"net/http"
yaml "gopkg.in/yaml.v2"
"github.com/coreos/poke/server"
"github.com/spf13/cobra"
)
func commandServe() *cobra.Command {
return &cobra.Command{
Use: "serve [ config file ]",
Short: "Connect to the storage and begin serving requests.",
Long: ``,
Example: "poke serve c.yaml",
RunE: serve,
}
}
func serve(cmd *cobra.Command, args []string) error {
switch len(args) {
default:
return errors.New("surplus arguments")
case 0:
// TODO(ericchiang): Consider having a default config file location.
return errors.New("no config file specified")
case 1:
}
configFile := args[0]
configData, err := ioutil.ReadFile(configFile)
if err != nil {
return fmt.Errorf("read config file %s: %v", configFile, err)
}
var c Config
if err := yaml.Unmarshal(configData, &c); err != nil {
return fmt.Errorf("parse config file %s: %v", configFile, err)
}
// Fast checks. Perform these first for a more responsive CLI.
checks := []struct {
bad bool
errMsg string
}{
{c.Issuer == "", "no issuer specified in config file"},
{len(c.Connectors) == 0, "no connectors supplied in config file"},
{c.Storage.Config == nil, "no storage suppied in config file"},
{c.Web.HTTP == "" && c.Web.HTTPS == "", "must supply a HTTP/HTTPS address to listen on"},
{c.Web.HTTPS != "" && c.Web.TLSCert == "", "no cert specified for HTTPS"},
{c.Web.HTTPS != "" && c.Web.TLSKey == "", "no private key specified for HTTPS"},
}
for _, check := range checks {
if check.bad {
return errors.New(check.errMsg)
}
}
connectors := make([]server.Connector, len(c.Connectors))
for i, conn := range c.Connectors {
if conn.Config == nil {
return fmt.Errorf("no config field for connector %q", conn.ID)
}
c, err := conn.Config.Open()
if err != nil {
return fmt.Errorf("open %s: %v", conn.ID, err)
}
connectors[i] = server.Connector{
ID: conn.ID,
DisplayName: conn.Name,
Connector: c,
}
}
s, err := c.Storage.Config.Open()
if err != nil {
return fmt.Errorf("initializing storage: %v", err)
}
serverConfig := server.Config{
Issuer: c.Issuer,
Connectors: connectors,
Storage: s,
}
serv, err := server.New(serverConfig)
if err != nil {
return fmt.Errorf("initializing server: %v", err)
}
errc := make(chan error, 2)
if c.Web.HTTP != "" {
go func() {
log.Printf("listening on %s", c.Web.HTTP)
errc <- http.ListenAndServe(c.Web.HTTP, serv)
}()
}
if c.Web.HTTPS != "" {
go func() {
log.Printf("listening on %s", c.Web.HTTPS)
errc <- http.ListenAndServeTLS(c.Web.HTTPS, c.Web.TLSCert, c.Web.TLSKey, serv)
}()
}
return <-errc
}

19
cmd/poke/version.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import (
"fmt"
"runtime"
"github.com/coreos/poke/version"
"github.com/spf13/cobra"
)
func commandVersion() *cobra.Command {
return &cobra.Command{
Use: "version",
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf(`v%s %s %s %s
`, version.Version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
},
}
}