<|start_filename|>pkg/handlers/health.go<|end_filename|>
// Copyright 2017 <NAME>. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package handlers

import (
	"net/http"

	"github.com/takama/bit"
	// Alternative of the Bit router with the same Router interface
	// "github.com/takama/k8sapp/pkg/router/httprouter"
)

// Health returns "OK" if service is alive
func (h *Handler) Health(c bit.Control) {
	c.Code(http.StatusOK)
	c.Body(http.StatusText(http.StatusOK))
}


<|start_filename|>pkg/handlers/ready_test.go<|end_filename|>
package handlers

import (
	"net/http"
	"testing"

	"github.com/takama/bit"
	// Alternative of the Bit router with the same Router interface
	// "github.com/takama/k8sapp/pkg/router/httprouter"
	"github.com/takama/k8sapp/pkg/config"
	"github.com/takama/k8sapp/pkg/logger"
	"github.com/takama/k8sapp/pkg/logger/standard"
)

func TestReady(t *testing.T) {
	h := New(standard.New(&logger.Config{}), new(config.Config))
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		h.Base(h.Ready)(bit.NewControl(w, r))
	})

	testHandler(t, handler, http.StatusOK, http.StatusText(http.StatusOK))
}


<|start_filename|>pkg/config/config.go<|end_filename|>
// Copyright 2017 <NAME>. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package config

import (
	"github.com/kelseyhightower/envconfig"
	"github.com/takama/k8sapp/pkg/logger"
)

const (
	// SERVICENAME contains a service name prefix which used in ENV variables
	SERVICENAME = "K8SAPP"
)

// Config contains ENV variables
type Config struct {
	// Local service host
	LocalHost string `split_words:"true"`
	// Local service port
	LocalPort int `split_words:"true"`
	// Logging level in logger.Level notation
	LogLevel logger.Level `split_words:"true"`
}

// Load settles ENV variables into Config structure
func (c *Config) Load(serviceName string) error {
	return envconfig.Process(serviceName, c)
}


<|start_filename|>pkg/system/signal_test.go<|end_filename|>
package system

import (
	"os"
	"syscall"
	"testing"

	"github.com/takama/k8sapp/pkg/logger"
	"github.com/takama/k8sapp/pkg/logger/standard"
)

const (
	testSignal                        = syscall.SIGUSR2
	customSignalType       SignalType = 777
	customSignalTypeString            = "777"
)

// testHandling implement simplest Operator interface
type testHandling struct {
	ch chan SignalType
}

// Reload implementation
func (th testHandling) Reload() error {
	th.ch <- Reload
	return ErrNotImplemented
}

// Maintenance implementation
func (th testHandling) Maintenance() error {
	th.ch <- Maintenance
	return ErrNotImplemented
}

// Shutdown implementation
func (th testHandling) Shutdown() error {
	th.ch <- Shutdown
	return ErrNotImplemented
}

func TestSignals(t *testing.T) {
	// Setup logger
	log := standard.New(&logger.Config{
		Level: logger.LevelDebug,
	})
	pid := os.Getpid()
	proc, err := os.FindProcess(pid)
	if err != nil {
		t.Error("Finding process:", err)
	}

	signals := NewSignals()

	shutdownSignals := signals.Get(Shutdown)
	verifySignal(t, syscall.SIGTERM, shutdownSignals, Shutdown)
	verifySignal(t, syscall.SIGINT, shutdownSignals, Shutdown)
	reloadSignals := signals.Get(Reload)
	verifySignal(t, syscall.SIGHUP, reloadSignals, Reload)
	maintenanceSignals := signals.Get(Maintenance)
	verifySignal(t, syscall.SIGUSR1, maintenanceSignals, Maintenance)

	handling := &testHandling{ch: make(chan SignalType, 1)}
	go signals.Wait(log, handling)

	// Prepare and send reload signal
	signals.Add(testSignal, Reload)
	sendSignal(t, handling.ch, proc, Reload)
	signals.Remove(testSignal, Reload)

	// Prepare and send maintenance signal
	signals.Add(testSignal, Maintenance)
	sendSignal(t, handling.ch, proc, Maintenance)
	signals.Remove(testSignal, Maintenance)

	// Prepare and send shutdown signal
	signals.Add(testSignal, Shutdown)
	sendSignal(t, handling.ch, proc, Shutdown)
	signals.Remove(testSignal, Shutdown)
}

func sendSignal(t *testing.T, ch <-chan SignalType, proc *os.Process, signal SignalType) {
	err := proc.Signal(testSignal)
	if err != nil {
		t.Error("Sending signal:", err)
		return
	}
	if sig := <-ch; sig != signal {
		t.Error("Expected signal:", signal, "got", sig)
	}
	return
}

func verifySignal(t *testing.T, signal os.Signal, signals []os.Signal, sigType SignalType) {
	if !isSignalAvailable(signal, signals) {
		t.Error("Absent of the signal:", signal, "among", sigType, "signal type")
	}
}

func TestSignalStringer(t *testing.T) {
	var s SignalType
	s = Shutdown
	if s.String() != "SHUTDOWN" {
		t.Error("Expected signal type SHUTDOWN, got", s.String())
	}
	s = Reload
	if s.String() != "RELOAD" {
		t.Error("Expected signal type RELOAD, got", s.String())
	}
	s = Maintenance
	if s.String() != "MAINTENANCE" {
		t.Error("Expected signal type MAINTENANCE, got", s.String())
	}
	s = customSignalType
	if s.String() != customSignalTypeString {
		t.Error("Expected signal type ", customSignalTypeString, "got", s.String())
	}
}

func TestRemoveNotExistingSignal(t *testing.T) {
	s := NewSignals()
	count := len(s.maintenance)
	s.Remove(syscall.SIGUSR2, Maintenance)
	if len(s.maintenance) != count {
		t.Error("Expected count of signals", count, "got", len(s.maintenance))
	}
}


<|start_filename|>Dockerfile<|end_filename|>
FROM scratch

ENV K8SAPP_LOCAL_HOST 0.0.0.0
ENV K8SAPP_LOCAL_PORT 8080
ENV K8SAPP_LOG_LEVEL 0

EXPOSE $K8SAPP_LOCAL_PORT

COPY certs /etc/ssl/certs/
COPY bin/linux-amd64/k8sapp /

CMD ["/k8sapp"]


<|start_filename|>pkg/service/service_test.go<|end_filename|>
package service

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/takama/bit"
	// Alternative of the Bit router with the same Router interface
	// "github.com/takama/k8sapp/pkg/router/httprouter"
	"github.com/takama/k8sapp/pkg/config"
	"github.com/takama/k8sapp/pkg/handlers"
)

func TestSetup(t *testing.T) {
	cfg := new(config.Config)
	err := cfg.Load(config.SERVICENAME)
	if err != nil {
		t.Error("Expected loading of environment vars, got", err)
	}
	router, logger, err := Setup(cfg)
	if err != nil {
		t.Errorf("Fail, got '%s', want '%v'", err, nil)
	}
	if router == nil {
		t.Error("Expected new router, got nil")
	}
	if logger == nil {
		t.Error("Expected new logger, got nil")
	}

	h := handlers.New(logger, cfg)
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		h.Base(notFound)(bit.NewControl(w, r))
	})

	req, err := http.NewRequest("GET", "/notfound", nil)
	if err != nil {
		t.Error(err)
	}

	trw := httptest.NewRecorder()
	handler.ServeHTTP(trw, req)

	if trw.Code != http.StatusNotFound {
		t.Error("Expected status:", http.StatusNotFound, "got", trw.Code)
	}
}
