blob: a32a00b7b620c97b77617b5e5e362323b83d4d8e [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ingress
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"math/rand"
"os"
"strings"
"syscall"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/apache/apisix-ingress-controller/pkg/config"
"github.com/apache/apisix-ingress-controller/pkg/log"
"github.com/apache/apisix-ingress-controller/pkg/types"
)
type fakeWriteSyncer struct {
buf bytes.Buffer
}
type fields struct {
Level string
Time string
Message string
}
func init() {
rand.Seed(int64(time.Now().Nanosecond()))
}
func (fws *fakeWriteSyncer) Sync() error {
return nil
}
func (fws *fakeWriteSyncer) Write(p []byte) (int, error) {
return fws.buf.Write(p)
}
func getRandomListen() string {
port := rand.Intn(10000) + 10000
return fmt.Sprintf("127.0.0.1:%d", port)
}
func TestSignalHandler(t *testing.T) {
cmd := NewIngressCommand()
listen := getRandomListen()
cmd.SetArgs([]string{
"--log-level", "debug",
"--log-output", "stderr",
"--http-listen", listen,
"--enable-profiling",
"--kubeconfig", "/foo/bar/baz",
"--resync-interval", "24h",
"--default-apisix-cluster-base-url", "http://apisixgw.default.cluster.local/apisix",
"--default-apisix-cluster-admin-key", "0x123",
})
waitCh := make(chan struct{})
go func() {
if err := cmd.Execute(); err != nil {
log.Errorf("failed to execute command: %s", err)
}
close(waitCh)
}()
time.Sleep(5 * time.Second)
fws := &fakeWriteSyncer{}
logger, err := log.NewLogger(log.WithLogLevel("info"), log.WithWriteSyncer(fws))
assert.Nil(t, err)
defer logger.Close()
log.DefaultLogger = logger
assert.Nil(t, syscall.Kill(os.Getpid(), syscall.SIGINT))
<-waitCh
msg := fws.buf.String()
assert.Contains(t, msg, fmt.Sprintf("signal %d (%s) received", syscall.SIGINT, syscall.SIGINT.String()))
assert.Contains(t, msg, "apisix ingress controller exited")
}
func TestNewIngressCommandEffectiveLog(t *testing.T) {
listen := getRandomListen()
cmd := NewIngressCommand()
cmd.SetArgs([]string{
"--log-level", "debug",
"--log-output", "./test.log",
"--http-listen", listen,
"--enable-profiling",
"--kubeconfig", "/foo/bar/baz",
"--resync-interval", "24h",
"--default-apisix-cluster-base-url", "http://apisixgw.default.cluster.local/apisix",
"--default-apisix-cluster-admin-key", "0x123",
})
defer os.Remove("./test.log")
stopCh := make(chan struct{})
go func() {
assert.Nil(t, cmd.Execute())
close(stopCh)
}()
time.Sleep(5 * time.Second)
assert.Nil(t, syscall.Kill(os.Getpid(), syscall.SIGINT))
<-stopCh
file, err := os.Open("./test.log")
assert.Nil(t, err)
buf := bufio.NewReader(file)
f := parseLog(t, buf)
assert.Contains(t, f.Message, "apisix ingress controller started")
assert.Equal(t, "info", f.Level)
f = parseLog(t, buf)
assert.Contains(t, f.Message, "version:")
assert.Equal(t, "info", f.Level)
f = parseLog(t, buf)
assert.Contains(t, f.Message, "use configuration")
assert.Equal(t, "info", f.Level)
var cfg config.Config
data := strings.TrimPrefix(f.Message, "use configuration\n")
err = json.Unmarshal([]byte(data), &cfg)
assert.Nil(t, err)
assert.Equal(t, "./test.log", cfg.LogOutput)
assert.Equal(t, "debug", cfg.LogLevel)
assert.Equal(t, listen, cfg.HTTPListen)
assert.Equal(t, true, cfg.EnableProfiling)
assert.Equal(t, "/foo/bar/baz", cfg.Kubernetes.Kubeconfig)
assert.Equal(t, types.TimeDuration{Duration: 24 * time.Hour}, cfg.Kubernetes.ResyncInterval)
assert.Equal(t, "0x123", cfg.APISIX.DefaultClusterAdminKey)
assert.Equal(t, "http://apisixgw.default.cluster.local/apisix", cfg.APISIX.DefaultClusterBaseURL)
}
func parseLog(t *testing.T, r *bufio.Reader) *fields {
line, isPrefix, err := r.ReadLine()
assert.False(t, isPrefix)
assert.Nil(t, err)
var f fields
err = json.Unmarshal(line, &f)
assert.Nil(t, err)
return &f
}
func TestRotateLog(t *testing.T) {
listen := getRandomListen()
cmd := NewIngressCommand()
cmd.SetArgs([]string{
"--log-rotate-output-path", "./testlog/test.log",
"--log-rotate-max-size", "1",
"--http-listen", listen,
"--enable-profiling",
"--kubeconfig", "/foo/bar/baz",
"--resync-interval", "24h",
"--default-apisix-cluster-base-url", "http://apisixgw.default.cluster.local/apisix",
"--default-apisix-cluster-admin-key", "0x123",
})
defer os.RemoveAll("./testlog/")
stopCh := make(chan struct{})
go func() {
assert.Nil(t, cmd.Execute())
close(stopCh)
}()
// fill logs with data until the size > 1m
line := ""
for i := 0; i < 256; i++ {
line += "0"
}
for i := 0; i < 4096; i++ {
log.Info(line)
}
time.Sleep(5 * time.Second)
assert.Nil(t, syscall.Kill(os.Getpid(), syscall.SIGINT))
<-stopCh
files, err := ioutil.ReadDir("./testlog")
if err != nil {
t.Fatalf("Unable to read log dir: %v", err)
}
assert.Equal(t, true, len(files) >= 2)
}