func init() { lf := kite.New("logfetcher", "0.0.1") lf.Config.DisableAuthentication = true lf.Config.Port = 3639 lf.HandleFunc("tail", Tail) go lf.Run() <-lf.ServerReadyNotify() remoteKite := kite.New("remote", "0.0.1") remoteKite.Config.Username = "******" remote = remoteKite.NewClient("http://127.0.0.1:3639/kite") err := remote.Dial() if err != nil { log.Fatalf("err") } remoteKite2 := kite.New("remote2", "0.0.1") remoteKite2.Config.Username = "******" remote2 = remoteKite2.NewClient("http://127.0.0.1:3639/kite") err = remote2.Dial() if err != nil { log.Fatalf("err") } }
func TestKitePingerPing(tt *testing.T) { Convey("Given a KitePinger", tt, func() { r := kite.New("remote", "0.0.0") r.Config.DisableAuthentication = true go r.Run() <-r.ServerReadyNotify() kiteURL := fmt.Sprintf("http://127.0.0.1:%d/kite", r.Port()) var shouldPingError bool r.HandleFunc("kite.ping", func(req *kite.Request) (interface{}, error) { if shouldPingError { return nil, errors.New("shouldPingError=true") } return "pong", nil }) Convey("When it can communicate with remote", func() { l := kite.New("local", "0.0.0").NewClient(kiteURL) So(l.Dial(), ShouldBeNil) p := NewKitePinger(l) Convey("It should return success", func() { So(p.Ping(), ShouldEqual, Success) }) }) Convey("When the kite is not dialed", func() { l := kite.New("local", "0.0.0").NewClient(kiteURL) p := NewKitePinger(l) Convey("It should return failure", func() { So(p.Ping(), ShouldEqual, Failure) }) }) Convey("When the remote kite returns an error", func() { shouldPingError = true l := kite.New("local", "0.0.0").NewClient(kiteURL) So(l.Dial(), ShouldBeNil) p := NewKitePinger(l) Convey("It should return failure", func() { So(p.Ping(), ShouldEqual, Failure) }) }) Convey("When the kite url is not responding", func() { l := kite.New("local", "0.0.0").NewClient(kiteURL) So(l.Dial(), ShouldBeNil) r.Close() p := NewKitePinger(l) Convey("It should return failure", func() { So(p.Ping(), ShouldEqual, Failure) }) }) }) }
func init() { storageKite = kite.New("storageKite", "0.0.1") storageKite.Config.DisableAuthentication = true storageKite.Config.Port = 3637 u, err := user.Current() if err != nil { panic(err) } db, err := openBoltDb(filepath.Join(u.HomeDir, "/.config/koding/klient.bolt")) if err != nil { log.Println("Can't use BoltDB: ", err) } s := New(db) storageKite.HandleFunc("get", s.GetValue) storageKite.HandleFunc("set", s.SetValue) storageKite.HandleFunc("delete", s.DeleteValue) go storageKite.Run() <-storageKite.ServerReadyNotify() remoteKite := kite.New("remote", "0.0.1") remoteKite.Config.Username = u.Username remote = remoteKite.NewClient("http://127.0.0.1:3637/kite") err = remote.Dial() if err != nil { log.Fatalf("err") } }
func TestMain(m *testing.M) { flag.Parse() kiteURL := testutil.GenKiteURL() sshkeys = kite.New("sshkeys", "0.0.1") sshkeys.Config.DisableAuthentication = true sshkeys.Config.Port = kiteURL.Port() sshkeys.HandleFunc("list", List) sshkeys.HandleFunc("add", Add) sshkeys.HandleFunc("delete", Delete) go sshkeys.Run() <-sshkeys.ServerReadyNotify() defer sshkeys.Close() u, err := user.Current() if err != nil { panic(err) } remoteKite := kite.New("remote", "0.0.1") remoteKite.Config.Username = u.Username remote = remoteKite.NewClient(kiteURL.String()) err = remote.Dial() if err != nil { log.Fatalf("err") } defer remoteKite.Close() os.Exit(m.Run()) }
func TestKite_MultipleDial(t *testing.T) { esrv := kite.New("echo-server", "0.0.0") esrv.Config.DisableAuthentication = true if err := esrv.Config.ReadEnvironmentVariables(); err != nil { t.Fatal(err) } esrv.HandleFunc("echo", func(r *kite.Request) (interface{}, error) { var arg string if err := r.Args.One().Unmarshal(&arg); err != nil { return nil, err } if arg == "" { return nil, errors.New("arg is empty") } return arg, nil }) ts := httptest.NewServer(esrv) ecli := kite.New("echo-client", "0.0.0") if err := ecli.Config.ReadEnvironmentVariables(); err != nil { t.Fatal(err) } esrv.SetLogLevel(kite.DEBUG) ecli.SetLogLevel(kite.DEBUG) c := ecli.NewClient(fmt.Sprintf("%s/kite", ts.URL)) if err := c.Dial(); err != nil { t.Fatalf("dialing echo-server kite error: %s", err) } if err := c.Dial(); err != nil { t.Fatalf("dialing echo-server kite error: %s", err) } resp, err := c.Tell("echo", "Hello world!") if err != nil { t.Fatalf("Tell()=%s", err) } var reply string if err := resp.Unmarshal(&reply); err != nil { t.Fatalf("Unmarshal()=%s", err) } if reply != "Hello world!" { t.Fatalf(`got %q, want "Hello world!"`, reply) } }
func TestMain(m *testing.M) { flag.Parse() // NOTE(rjeczalik): copy testdata/testfile1.txt so after test execution // the file is not modified. if err := testutil.FileCopy("testdata/testfile1.txt", testfile1); err != nil { panic(err) } kiteURL := testutil.GenKiteURL() fs = kite.New("fs", "0.0.1") fs.Config.DisableAuthentication = true fs.Config.Port = kiteURL.Port() fs.HandleFunc("readDirectory", ReadDirectory) fs.HandleFunc("glob", Glob) fs.HandleFunc("readFile", ReadFile) fs.HandleFunc("writeFile", WriteFile) fs.HandleFunc("uniquePath", UniquePath) fs.HandleFunc("getInfo", GetInfo) fs.HandleFunc("setPermissions", SetPermissions) fs.HandleFunc("remove", Remove) fs.HandleFunc("rename", Rename) fs.HandleFunc("createDirectory", CreateDirectory) fs.HandleFunc("move", Move) fs.HandleFunc("copy", Copy) fs.HandleFunc("getDiskInfo", GetDiskInfo) go fs.Run() <-fs.ServerReadyNotify() defer fs.Close() remoteKite := kite.New("remote", "0.0.1") remoteKite.Config.Username = "******" remote = remoteKite.NewClient(kiteURL.String()) err := remote.Dial() if err != nil { log.Fatalf("err") } defer remoteKite.Close() remoteKite2 := kite.New("remote2", "0.0.1") remoteKite2.Config.Username = "******" remote2 = remoteKite2.NewClient(kiteURL.String()) err = remote2.Dial() if err != nil { log.Fatalf("err") } defer remoteKite2.Close() os.Exit(m.Run()) }
func TestCheckSizeOfRemotefolder(t *testing.T) { type ExecResponse struct { Stdout string `json:"stdout"` Stderr string `json:"stderr"` ExitStatus int `json:"exitStatus"` } // The response that we're going to return on each exec call var ( expectedPath string = "/foo" requestedPath string ) s := kite.New("s", "0.0.0") s.Config.DisableAuthentication = true s.HandleFunc("fs.getPathSize", func(r *kite.Request) (interface{}, error) { var params struct { Path string } if r.Args.One().Unmarshal(¶ms) != nil || params.Path == "" { return nil, errors.New("{path : [string]}") } requestedPath = params.Path return int64(1200000000), nil }) ts := httptest.NewServer(s) c := kite.New("c", "0.0.0").NewClient(fmt.Sprintf("%s/kite", ts.URL)) res, err := checkSizeOfRemoteFolder(&machine.Machine{Transport: c}, expectedPath) if err != nil { t.Error(err) } if expectedPath != requestedPath { t.Error("Expected path to be the same as requested. expected:%s, got:%s", expectedPath, requestedPath) } // Should return a string warning, ok := res.(string) if !ok { t.Errorf("checkSizeOfRemote did not return a string. Got '%#v'", res) } // Should return a warning if the filesize is too big if warning == "" { t.Errorf("checkSizeOfRemote should have returned a warning. Got an empty string instead.") } }
func NewKiteWrapper(cfg *conf.KiteConfig) *Wrapper { k := kite.New(cfg.Name, cfg.Version) k.Config = config.MustGet() k.Config.Port = cfg.Port return &Wrapper{k, cfg} }
// NewServerKite creates a server kite for the given server. func NewServerKite(s *Server, name, version string) (*kite.Kite, error) { k := kite.New(name, version) if s.opts.Config == nil { cfg, err := config.Get() if err != nil { return nil, err } s.opts.Config = cfg } s.opts.Config.KontrolURL = s.opts.kontrolURL() s.opts.Config.Transport = config.XHRPolling if s.opts.Port != 0 { s.opts.Config.Port = s.opts.Port } if s.opts.Region != "" { s.opts.Config.Region = s.opts.Region } if s.opts.Environment != "" { s.opts.Config.Environment = s.opts.Environment } if s.opts.Test { s.opts.Config.DisableAuthentication = true } if s.opts.Debug { k.SetLogLevel(kite.DEBUG) } k.Log = s.opts.Log k.Config = s.opts.Config k.ClientFunc = httputil.ClientFunc(s.opts.Debug) if fn := s.metricsFunc(); fn != nil { k.PreHandleFunc(fn) } k.HandleFunc("register", s.Register) k.HandleFunc("registerServices", s.RegisterServices) k.HandleHTTPFunc("/healthCheck", artifact.HealthCheckHandler(name)) k.HandleHTTPFunc("/version", artifact.VersionHandler()) // Tunnel helper methods, like ports, stats etc. k.HandleHTTPFunc("/-/discover/{service}", s.discoverHandler()) // Route all the rest requests (match all paths that does not begin with /-/). k.HandleHTTP(`/{rest:.?$|[^\/].+|\/[^-].+|\/-[^\/].*}`, s.serverHandler()) u, err := url.Parse(s.opts.registerURL()) if err != nil { return nil, fmt.Errorf("error parsing registerURL: %s", err) } if err := k.RegisterForever(u); err != nil { return nil, fmt.Errorf("error registering to Kontrol: %s", err) } return k, nil }
// New creates a new kontrol instance with the given version and config // instance. Publickey is used for validating tokens and privateKey is used for // signing tokens. // // Public and private keys are RSA pem blocks that can be generated with the // following command: // openssl genrsa -out testkey.pem 2048 // openssl rsa -in testkey.pem -pubout > testkey_pub.pem // func New(conf *config.Config, version string) *Kontrol { k := kite.New("kontrol", version) k.Config = conf // Listen on 4000 by default if k.Config.Port == 0 { k.Config.Port = DefaultPort } kontrol := &Kontrol{ Kite: k, log: k.Log, clientLocks: NewIdlock(), heartbeats: make(map[string]*time.Timer, 0), lastIDs: make([]string, 0), lastPublic: make([]string, 0), lastPrivate: make([]string, 0), } k.HandleFunc("register", kontrol.handleRegister) k.HandleFunc("registerMachine", kontrol.handleMachine).DisableAuthentication() k.HandleFunc("getKites", kontrol.handleGetKites) k.HandleFunc("getToken", kontrol.handleGetToken) k.HandleFunc("getKey", kontrol.handleGetKey) k.HandleHTTPFunc("/register", kontrol.handleRegisterHTTP) k.HandleHTTPFunc("/heartbeat", kontrol.handleHeartbeat) return kontrol }
func WaitTillConnected(conf *Config, timeout time.Duration, hks ...*HelloKite) error { k := kite.New("WaitTillConnected", "1.0.0") k.Config = conf.Config.Copy() t := time.After(timeout) for { select { case <-t: return fmt.Errorf("timed out waiting for %v after %s", hks, timeout) default: kites, err := k.GetKites(&protocol.KontrolQuery{ Version: "1.0.0", }) if err != nil && err != kite.ErrNoKitesAvailable { return err } notReady := make(map[string]struct{}, len(hks)) for _, hk := range hks { notReady[hk.Kite.Kite().ID] = struct{}{} } for _, kite := range kites { delete(notReady, kite.Kite.ID) } if len(notReady) == 0 { return nil } } } }
func main() { // Create a kite k := kite.New("math", "1.0.0") // Add pre handler method k.PreHandleFunc(func(r *kite.Request) (interface{}, error) { fmt.Println("\nThis pre handler is executed before the method is executed") // let us return an hello to base square method! return "hello from pre handler!", nil }) // Add post handler method k.PostHandleFunc(func(r *kite.Request) (interface{}, error) { fmt.Println("This post handler is executed after the method is executed") // pass the response from the previous square method back to the // client, this is imporant if you use post handler return r.Response, nil }) // Add our handler method, authentication is disabled for this example k.HandleFunc("square", Square).DisableAuthentication().PreHandleFunc(func(r *kite.Request) (interface{}, error) { fmt.Println("This pre handler is only valid for this individual method") return nil, nil }) // Attach to a server and run it k.Config.Port = 3636 k.Run() }
func New(conf *config.Config, version, pubKey, privKey string) *Proxy { k := kite.New("tunnelproxy", version) k.Config = conf // Listen on 3999 by default if k.Config.Port == 0 { k.Config.Port = DefaultPort } p := &Proxy{ Kite: k, readyC: make(chan bool), closeC: make(chan bool), pubKey: pubKey, privKey: privKey, kites: make(map[string]*PrivateKite), mux: http.NewServeMux(), RegisterToKontrol: true, PublicHost: DefaultPublicHost, } p.Kite.HandleFunc("register", p.handleRegister) p.mux.Handle("/", p.Kite) p.mux.Handle("/proxy/", sockjsHandlerWithRequest("/proxy", sockjs.DefaultOptions, p.handleProxy)) // Handler for clients outside p.mux.Handle("/tunnel/", sockjsHandlerWithRequest("/tunnel", sockjs.DefaultOptions, p.handleTunnel)) // Handler for kites behind // Remove URL from the map when PrivateKite disconnects. k.OnDisconnect(func(r *kite.Client) { delete(p.kites, r.Kite.ID) }) return p }
// NewWithoutHandlers creates a new kontrol instance with the given version and config // instance, but *without* the default handlers. If this is function is // used, make sure to implement the expected kontrol functionality. // // Example: // // kontrol := NewWithoutHandlers(conf, version) // kontrol.Kite.HandleFunc("register", kontrol.HandleRegister) // kontrol.Kite.HandleFunc("registerMachine", kontrol.HandleMachine).DisableAuthentication() // kontrol.Kite.HandleFunc("getKites", kontrol.HandleGetKites) // kontrol.Kite.HandleFunc("getToken", kontrol.HandleGetToken) // kontrol.Kite.HandleFunc("getKey", kontrol.HandleGetKey) // kontrol.Kite.HandleHTTPFunc("/heartbeat", kontrol.HandleHeartbeat) // kontrol.Kite.HandleHTTPFunc("/register", kontrol.HandleRegisterHTTP) // func NewWithoutHandlers(conf *config.Config, version string) *Kontrol { k := &Kontrol{ clientLocks: NewIdlock(), heartbeats: make(map[string]*heartbeat), closed: make(chan struct{}), tokenCache: make(map[string]string), } // Make a copy to not modify user-provided value. conf = conf.Copy() // Listen on 4000 by default. if conf.Port == 0 { conf.Port = DefaultPort } // Allow keys that were recently deleted - for Register{,HTTP} to // give client kite a chance to update them. if conf.VerifyFunc == nil { conf.VerifyFunc = k.Verify } k.Kite = kite.New("kontrol", version) k.Kite.Config = conf k.log = k.Kite.Log return k }
// CreateKlientClient creates a kite to the klient specified by KlientOptions. // In most cases CreateKlientWithDefaultOpts should be used instead of this, ie // this should be used only if you want to override KlientOptions. func CreateKlientClient(opts KlientOptions) (*kite.Client, error) { if opts.Version == "" { return nil, errors.New("CreateKlientClient: Version is required") } if opts.Address == "" { return nil, errors.New("CreateKlientClient: Address is required") } k := kite.New(opts.Name, opts.Version) k.Config.Environment = opts.Environment c := k.NewClient(opts.Address) if opts.KiteKey != "" { c.Auth = &kite.Auth{ Type: "kiteKey", Key: opts.KiteKey, } } else if opts.KiteKeyPath != "" { // If a key path is declared, load it and setup auth. data, err := ioutil.ReadFile(opts.KiteKeyPath) if err != nil { return nil, err } c.Auth = &kite.Auth{ Type: "kiteKey", Key: strings.TrimSpace(string(data)), } } return c, nil }
func main() { // Create a kite k := kite.New("exp2", "1.0.0") k.Config = config.MustGet() onEvent := func(e *kite.Event, err *kite.Error) { fmt.Printf("e %+v\n", e) fmt.Printf("err %+v\n", err) } _, err := k.WatchKites(protocol.KontrolQuery{ Username: k.Config.Username, Environment: k.Config.Environment, Name: "math", // ID: "48bb002b-79f6-4a4e-6bba-a40567a08b6c", }, onEvent) if err != nil { log.Fatalln(err) } // This is a bad example, it's just for testing the watch functionality :) fmt.Println("listening to events") select {} }
// NewClient returns client with required properties for accessing remote // klient. func NewClient() (*Client, error) { // Parse kite.key only once. if err := once.Do(newConfig); err != nil { return nil, err } k := kite.New(Name, Version) k.Config = config.Copy() if debug { k.SetLogLevel(kite.DEBUG) } c := &Client{ Kite: k, Log: logging.NewCustom(Name, debug), } c.Log.Debug("starting provider-vagrant in debug mode") c.Vagrant = &vagrantapi.Klient{ Kite: k, Log: c.Log.New("vagrantapi"), Debug: debug, } return c, nil }
func main() { // Create a kite k := kite.New("exp2", "1.0.0") // Create mathworker client mathWorker := k.NewClient("http://localhost:3636/kite") // Connect to remote kite connected, err := mathWorker.DialForever() if err != nil { k.Log.Fatal(err.Error()) } // Wait until connected <-connected // Call square method every second for _ = range time.Tick(time.Second) { i := rand.Intn(10) // Call a method of mathworker kite response, err := mathWorker.TellWithTimeout("square", 4*time.Second, i) if err != nil { k.Log.Error(err.Error()) continue } // Print the result result := response.MustFloat64() fmt.Printf("input: %d result: %.0f\n", i, result) } }
func main() { flag.Parse() // Create a kite k := kite.New("math", "1.0.0") // Add our handler method k.HandleFunc("square", Square) // Get config from kite.Key directly, usually it's under ~/.kite/kite.key c := config.MustGet() k.Config = c k.Config.Port = *flagPort k.SetLogLevel(kite.DEBUG) k.Id = c.Id // by default it's already WebSocket if *flagTransport != "" && *flagTransport == "xhrpolling" { k.Config.Transport = config.XHRPolling } // Register to kite with this url kiteURL := &url.URL{Scheme: "http", Host: "localhost:" + strconv.Itoa(*flagPort), Path: "/kite"} // Register us ... err := k.RegisterForever(kiteURL) if err != nil { log.Fatal(err) } // And finally attach to a server and run it k.Run() }
func main() { flag.Parse() // Create a kite. k := kite.New("exp2", "1.0.0") // Connect to our math kite. mathWorker := k.NewClient(math.Host.URL.String()) err := mathWorker.Dial() if err != nil { panic(err) } // Call square method with the given argument. response, err := mathWorker.Tell("square", &math.Request{ Number: *arg, Name: "math-cli", }) if err != nil { panic(err) } fmt.Println("result:", response.MustFloat64()) }
func TestGetKites(t *testing.T) { testName := "mathworker4" testVersion := "1.1.1" m := kite.New(testName, testVersion) m.Config = conf.Config.Copy() defer m.Close() kiteURL := &url.URL{Scheme: "http", Host: "localhost:4444", Path: "/kite"} _, err := m.Register(kiteURL) if err != nil { t.Error(err) } defer m.Close() query := &protocol.KontrolQuery{ Username: conf.Config.Username, Environment: conf.Config.Environment, Name: testName, Version: "1.1.1", } // exp2 queries for mathkite exp3 := kite.New("exp3", "0.0.1") exp3.Config = conf.Config.Copy() defer exp3.Close() kites, err := exp3.GetKites(query) if err != nil { t.Fatal(err) } defer klose(kites) if len(kites) == 0 { t.Fatal("No mathworker available") } if len(kites) != 1 { t.Fatalf("Only one kite is registerd, we have %d", len(kites)) } if kites[0].Name != testName { t.Errorf("getkites got %s exptected %", kites[0].Name, testName) } if kites[0].Version != testVersion { t.Errorf("getkites got %s exptected %", kites[0].Version, testVersion) } }
// NewClient gives new, unstarted tunnel client for the given options. func NewClient(opts *ClientOptions) (*Client, error) { optsCopy := *opts if optsCopy.Log == nil { optsCopy.Log = logging.NewCustom("tunnelclient", optsCopy.Debug) } // TODO(rjeczalik): fix production to use WebSocket by default // // BUG(rjeczalik): starting a kite that is not registered to // kontrol will prevent the kite from updating it's keypair, // when it changes in kontrol - the only fix is to restart // kite process. k := kite.New("tunnelclient", "0.0.1") k.Config = optsCopy.Kite.Config.Copy() k.Config.Transport = config.WebSocket c := &Client{ kite: k, opts: &optsCopy, tunnelKiteURL: optsCopy.tunnelKiteURL(), stateChanges: make(chan *tunnel.ClientStateChange, 128), regserv: make(chan map[string]*Tunnel, 1), services: make(Services), routes: make(map[int]string), } // If VirtualHost was configured, try to connect to it first. if c.opts.LastVirtualHost != "" { c.tunnelKiteURL = fmt.Sprintf("http://%s/kite", c.opts.LastVirtualHost) c.connected = &RegisterResult{ VirtualHost: c.opts.LastVirtualHost, ServerAddr: c.opts.LastVirtualHost, } } c.kite.ClientFunc = httputil.ClientFunc(opts.Debug) cfg := &tunnel.ClientConfig{ FetchIdentifier: c.fetchIdent, FetchServerAddr: c.fetchServerAddr, FetchLocalAddr: c.fetchLocalAddr, LocalAddr: c.opts.LocalAddr, Debug: c.opts.Debug, Log: c.opts.Log.New("transport"), StateChanges: c.stateChanges, } client, err := tunnel.NewClient(cfg) if err != nil { return nil, err } c.client = client return c, nil }
func main() { k := kite.New("ex", "1.0.0") k.Config.Port = 8081 k.HandleHTTPFunc("/", func(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(model.GetData()) }) k.Run() }
func TestHome(t *testing.T) { Convey("Given Home is called", t, func() { s := kite.New("s", "0.0.0") s.Config.DisableAuthentication = true s.HandleFunc("os.home", Home) ts := httptest.NewServer(s) c := kite.New("c", "0.0.0").NewClient(fmt.Sprintf("%s/kite", ts.URL)) So(c.Dial(), ShouldBeNil) Convey("It should require username field", func() { _, err := c.Tell("os.home") So(err, ShouldNotBeNil) _, err = c.Tell("os.home", struct { NotUsername string }{ NotUsername: "******", }) So(err, ShouldNotBeNil) }) Convey("Given a username that exists", func() { userLookup = func(string) (*user.User, error) { return &user.User{ HomeDir: "/home/foo", }, nil } Convey("It should return that users home", func() { res, err := c.Tell("os.home", struct { Username string }{ Username: "******", }) So(err, ShouldBeNil) var home string So(res.Unmarshal(&home), ShouldBeNil) So(home, ShouldEqual, "/home/foo") }) }) }) }
func TestApplyAndDestroy(t *testing.T) { local := kite.New("testing", "1.0.0") withKite(t, func(k *kite.Kite) error { // Connect to our terraformer kite tfr := local.NewClient(k.RegisterURL(true).String()) defer tfr.Close() tfr.Dial() req := TerraformRequest{ Content: SampleTFJSON, Variables: variables, ContentID: "test_file", } response, err := tfr.Tell("apply", req) if err != nil { return err } res := terraform.State{} if err := response.Unmarshal(&res); err != nil { return err } if len(res.Modules) != 1 { return fmt.Errorf("expected Modules to have length 1, got: %d", len(res.Modules)) } if len(res.Modules[0].Resources) != 7 { return fmt.Errorf("expected Resources to have length 7, got: %d", len(res.Modules[0].Resources)) } response, err = tfr.Tell("destroy", req) if err != nil { return err } res = terraform.State{} if err := response.Unmarshal(&res); err != nil { return err } if len(res.Modules) != 1 { return fmt.Errorf("expected Modules to have length 1, got: %d", len(res.Modules)) } if len(res.Modules[0].Resources) != 0 { return fmt.Errorf("expected Resources to have length 0, got: %d", len(res.Modules[0].Resources)) } return nil }) }
func TestTokenInvalidation(t *testing.T) { oldval := TokenTTL defer func() { TokenTTL = oldval }() TokenTTL = time.Millisecond * 500 TokenLeeway = 0 testName := "mathworker6" testVersion := "1.1.1" m := kite.New(testName, testVersion) m.Config = conf.Copy() m.Config.Port = 6666 kiteURL := &url.URL{Scheme: "http", Host: "localhost:6666", Path: "/mathworker6"} _, err := m.Register(kiteURL) if err != nil { t.Error(err) } defer m.Close() token, err := m.GetToken(m.Kite()) if err != nil { t.Error(err) } time.Sleep(time.Millisecond * 700) token2, err := m.GetToken(m.Kite()) if err != nil { t.Error(err) } if token == token2 { t.Error("token invalidation doesn't work") } TokenTTL = time.Second * 4 token3, err := m.GetToken(m.Kite()) if err != nil { t.Error(err) } token4, err := m.GetToken(m.Kite()) if err != nil { t.Error(err) } if token3 != token4 { t.Error("tokens should be the same") } }
func (kt *KiteTransport) kite() *kite.Kite { if kt.k != nil { return kt.k } kt.k = kite.New(config.Name, config.KiteVersion) kt.k.Config = kt.kiteConfig() kt.k.Log = kt.log() return kt.k }
func main() { k := kite.New("first", "1.0.0") k.Config.Port = 6000 k.HandleFunc("square", func(r *kite.Request) (interface{}, error) { a := r.Args.One().MustFloat64() fmt.Println("get input %f", a) return a * a, nil }) k.Register(&url.URL{Scheme: "http", Host: "localhost:6000/kite"}) k.Run() }
func TestRegisterDenyEvil(t *testing.T) { // TODO(rjeczalik): use sentinel error value instead const authErr = "no valid authentication key found" legit, err := NewHelloKite("testuser", conf) if err != nil { t.Fatal(err) } if _, err = legit.Kite.GetToken(legit.Kite.Kite()); err != nil { t.Fatal(err) } evil := kite.New("testuser", "1.0.0") evil.Config = conf.Config.Copy() evil.Config.Port = 6767 evil.Config.Username = "******" evil.Config.KontrolUser = "******" evil.Config.KontrolURL = conf.Config.KontrolURL evil.Config.KiteKey = testutil.NewToken("testuser", testkeys.PrivateEvil, testkeys.PublicEvil).Raw // KontrolKey can be easily extracted from existing kite.key evil.Config.KontrolKey = testkeys.Public evil.Config.ReadEnvironmentVariables() evilURL := &url.URL{ Scheme: "http", Host: "127.0.0.1:6767", Path: "/kite", } _, err = evil.Register(evilURL) if err == nil { t.Errorf("expected kontrol to deny register request: %s", evil.Kite()) } else { t.Logf("register denied: %s", err) } _, err = evil.GetToken(legit.Kite.Kite()) if err == nil { t.Errorf("expected kontrol to deny token request: %s", evil.Kite()) } else { t.Logf("token denied: %s", err) } _, err = evil.TellKontrolWithTimeout("registerMachine", 4*time.Second, map[string]interface{}{}) if err == nil { t.Fatal("expected registerMachine to fail") } if !strings.Contains(err.Error(), authErr) { t.Fatalf("got %q, want %q error", err, authErr) } }
func TestPlanWithLockedResource(t *testing.T) { local := kite.New("testing", "1.0.0") withKite(t, func(k *kite.Kite) error { // Connect to our terraformer kite tfr := local.NewClient(k.RegisterURL(true).String()) defer tfr.Close() tfr.Dial() callCount := 10 var wg sync.WaitGroup wg.Add(callCount) fail := 0 success := 0 var mu sync.Mutex for i := 0; i < callCount; i++ { go func(seq int) { req := TerraformRequest{ Content: SampleTFJSON, Variables: variables, ContentID: "test_file_locked", } _, err := tfr.Tell("plan", req) mu.Lock() if err != nil { fail++ } else { success++ } mu.Unlock() wg.Done() }(i) } wg.Wait() if fail < callCount-1 { return fmt.Errorf("fail should be lt %d, got %d", callCount-1, fail) } if success != 1 { return fmt.Errorf("success should be 1, got %d", success) } return nil }) }