Example #1
0
func main() {
	var (
		err       error
		closeChan = make(chan bool)
	)

	leapsConfig := LeapsConfig{
		NumProcesses:         runtime.NumCPU(),
		LoggerConfig:         log.DefaultLoggerConfig(),
		StatsConfig:          log.DefaultStatsConfig(),
		RiemannConfig:        log.NewRiemannClientConfig(),
		StoreConfig:          store.NewConfig(),
		AuthenticatorConfig:  auth.NewConfig(),
		CuratorConfig:        lib.DefaultCuratorConfig(),
		HTTPServerConfig:     net.DefaultHTTPServerConfig(),
		InternalServerConfig: net.NewInternalServerConfig(),
		StatsServerConfig:    log.DefaultStatsServerConfig(),
	}

	// A list of default config paths to check for if not explicitly defined
	defaultPaths := []string{}

	/* If we manage to get the path of our executable then we want to try and find config files
	 * relative to that path, we always check from the parent folder since we assume leaps is
	 * stored within the bin folder.
	 */
	if executablePath, err := path.BinaryPath(); err == nil {
		defaultPaths = append(defaultPaths, filepath.Join(executablePath, "..", "config.yaml"))
		defaultPaths = append(defaultPaths, filepath.Join(executablePath, "..", "config", "leaps.yaml"))
		defaultPaths = append(defaultPaths, filepath.Join(executablePath, "..", "config.json"))
		defaultPaths = append(defaultPaths, filepath.Join(executablePath, "..", "config", "leaps.json"))
	}

	defaultPaths = append(defaultPaths, []string{
		filepath.Join(".", "leaps.yaml"),
		filepath.Join(".", "leaps.json"),
		"/etc/leaps.yaml",
		"/etc/leaps.json",
		"/etc/leaps/config.yaml",
		"/etc/leaps/config.json",
	}...)

	// Load configuration etc
	if !util.Bootstrap(&leapsConfig, defaultPaths...) {
		return
	}

	if len(*sharePathOverride) > 0 {
		leapsConfig.AuthenticatorConfig.FileConfig.SharePath = *sharePathOverride
		leapsConfig.StoreConfig.StoreDirectory = *sharePathOverride
	}

	runtime.GOMAXPROCS(leapsConfig.NumProcesses)

	// Logging and stats aggregation
	logger := log.NewLogger(os.Stdout, leapsConfig.LoggerConfig)
	stats := log.NewStats(leapsConfig.StatsConfig)

	if riemannClient, err := log.NewRiemannClient(leapsConfig.RiemannConfig); err == nil {
		logger.UseRiemann(riemannClient)
		stats.UseRiemann(riemannClient)

		defer riemannClient.Close()
	} else if err != log.ErrEmptyConfigAddress {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("Riemann client error: %v\n", err))
		return
	}
	defer stats.Close()

	fmt.Printf("Launching a leaps instance, use CTRL+C to close.\n\n")

	// Document storage engine
	documentStore, err := store.Factory(leapsConfig.StoreConfig)
	if err != nil {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("Document store error: %v\n", err))
		return
	}

	// Authenticator
	authenticator, err := auth.Factory(leapsConfig.AuthenticatorConfig, logger, stats)
	if err != nil {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("Authenticator error: %v\n", err))
		return
	}

	// Curator of documents
	curator, err := lib.NewCurator(leapsConfig.CuratorConfig, logger, stats, authenticator, documentStore)
	if err != nil {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("Curator error: %v\n", err))
		return
	}
	defer curator.Close()

	// HTTP API
	leapHTTP, err := net.CreateHTTPServer(curator, leapsConfig.HTTPServerConfig, logger, stats)
	if err != nil {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("HTTP error: %v\n", err))
		return
	}
	defer leapHTTP.Stop()

	go func() {
		if httperr := leapHTTP.Listen(); httperr != nil {
			fmt.Fprintln(os.Stderr, fmt.Sprintf("Http listen error: %v\n", httperr))
		}
		closeChan <- true
	}()

	var adminRegister register.EndpointRegister

	// Internal admin HTTP API
	if 0 < len(leapsConfig.InternalServerConfig.Address) {
		adminHTTP, err := net.NewInternalServer(curator, leapsConfig.InternalServerConfig, logger, stats)
		if err != nil {
			fmt.Fprintln(os.Stderr, fmt.Sprintf("Admin HTTP error: %v\n", err))
			return
		}
		adminRegister = adminHTTP

		go func() {
			if httperr := adminHTTP.Listen(); httperr != nil {
				fmt.Fprintln(os.Stderr, fmt.Sprintf("Admin HTTP listen error: %v\n", httperr))
			}
			closeChan <- true
		}()
	}

	// Register for allowing other components to set API endpoints.
	register := newEndpointsRegister(leapHTTP, adminRegister)
	if err = authenticator.RegisterHandlers(register); err != nil {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("Register authentication endpoints failed: %v\n", err))
		return
	}

	// Internal Statistics HTTP API
	statsServer, err := log.NewStatsServer(leapsConfig.StatsServerConfig, logger, stats)
	if err != nil {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("Stats error: %v\n", err))
		return
	}

	go func() {
		if statserr := statsServer.Listen(); statserr != nil {
			fmt.Fprintln(os.Stderr, fmt.Sprintf("Stats server listen error: %v\n", statserr))
		}
	}()

	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)

	// Wait for termination signal
	select {
	case <-sigChan:
	case <-closeChan:
	}
}
Example #2
0
func TestHttpServer(t *testing.T) {
	bytes, err := ioutil.ReadFile("../test/stories/binder_stories.js")
	if err != nil {
		t.Errorf("Read file error: %v", err)
		return
	}

	var scont binderStoriesContainer
	if err := json.Unmarshal(bytes, &scont); err != nil {
		t.Errorf("Story parse error: %v", err)
		return
	}

	httpServerConfig := DefaultHTTPServerConfig()
	httpServerConfig.Address = "localhost:8254"

	logger, stats := loggerAndStats()
	auth, storage := authAndStore(logger, stats)

	curator, err := lib.NewCurator(lib.DefaultCuratorConfig(), logger, stats, auth, storage)
	if err != nil {
		t.Errorf("Curator error: %v", err)
	}

	go func() {
		http, err := CreateHTTPServer(curator, httpServerConfig, logger, stats)
		if err != nil {
			t.Errorf("Create HTTP error: %v", err)
			return
		}
		if err = http.Listen(); err != nil {
			t.Errorf("Listen error: %v", err)
		}
	}()

	time.Sleep(50 * time.Millisecond)

	origin := "http://localhost/"
	url := "ws://localhost:8254/leaps/socket"

	for _, story := range scont.Stories {

		ws, err := websocket.Dial(url, "", origin)
		if err != nil {
			t.Errorf("client connect error: %v", err)
			return
		}

		websocket.JSON.Send(ws, LeapClientMessage{
			Command: "create",
			Document: &store.Document{
				Content: story.Content,
			},
		})

		var initResponse LeapServerMessage
		if err := websocket.JSON.Receive(ws, &initResponse); err != nil {
			t.Errorf("Init receive error: %v", err)
			return
		}

		switch initResponse.Type {
		case "document":
		case "error":
			t.Errorf("Server returned error: %v", initResponse.Error)
			return
		default:
			t.Errorf("unexpected message type from server init: %v", initResponse.Type)
			return
		}

		feeds := make(chan lib.OTransform)

		wg := sync.WaitGroup{}
		wg.Add(10)

		go senderClient(initResponse.Document.ID, feeds, t)
		for j := 0; j < 10; j++ {
			go goodStoryClient(initResponse.Document.ID, &story, &wg, t)
		}

		time.Sleep(50 * time.Millisecond)

		for j := 0; j < len(story.Transforms); j++ {
			feeds <- story.Transforms[j]
		}

		wg.Wait()
	}

	curator.Close()
}