refactor: remove built-in daemon manager (#2183)

This commit is contained in:
bzp2010 2021-11-02 03:02:27 -05:00 committed by GitHub
parent e1e83e3d9a
commit 32183799dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 608 additions and 1074 deletions

1
.github/actions/tmate-action vendored Submodule

@ -0,0 +1 @@
Subproject commit 19a49ed72830f0810df81e42252ee9da19c8e4d8

View File

@ -29,6 +29,8 @@ jobs:
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: cache etcd
id: cache-etcd
@ -45,6 +47,15 @@ jobs:
wget https://github.com/etcd-io/etcd/releases/download/v${{ matrix.etcd }}/etcd-v${{ matrix.etcd }}-linux-amd64.tar.gz
tar zxvf etcd-v${{ matrix.etcd }}-linux-amd64.tar.gz
- name: install bats
run: |
git clone https://github.com/sstephenson/bats.git && cd bats
sudo ./install.sh /usr/local
- name: run test
working-directory: ./api
run: sudo ./test/shell/cli_test.sh
run: chmod +x ./test/shell/cli_test.sh && sudo ./test/shell/cli_test.sh
- name: tmate debugger
if: ${{ failure() }}
uses: ./.github/actions/tmate-action

3
.gitmodules vendored
View File

@ -4,3 +4,6 @@
[submodule ".github/actions/paths-filter"]
path = .github/actions/paths-filter
url = https://github.com/dorny/paths-filter.git
[submodule ".github/actions/tmate-action"]
path = .github/actions/tmate-action
url = https://github.com/mxschmitt/action-tmate

View File

@ -1,38 +0,0 @@
/*
* 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 cmd
import (
"fmt"
"github.com/spf13/cobra"
)
var service *Service
func newInstallCommand() *cobra.Command {
return &cobra.Command{
Use: "install",
Short: "re-install Apache APISIX Dashboard service",
RunE: func(cmd *cobra.Command, args []string) error {
serviceState.installService = true
status, err := service.manageService()
fmt.Println(status)
return err
},
}
}

View File

@ -1,36 +0,0 @@
/*
* 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 cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func newRemoveCommand() *cobra.Command {
return &cobra.Command{
Use: "remove",
Short: "remove Apache APISIX Dashboard service",
RunE: func(cmd *cobra.Command, args []string) error {
serviceState.removeService = true
status, err := service.manageService()
fmt.Println(status)
return err
},
}
}

View File

@ -29,12 +29,8 @@ import (
"github.com/apisix/manager-api/internal/log"
)
var (
forceStart bool
)
var rootCmd = &cobra.Command{
Use: "manager-api [flags]",
Use: "manager-api",
Short: "Apache APISIX Manager API",
RunE: func(cmd *cobra.Command, args []string) error {
err := manageAPI()
@ -43,31 +39,17 @@ var rootCmd = &cobra.Command{
}
func init() {
cobra.OnInitialize(func() {
var err error
service, err = createService()
if err != nil {
fmt.Fprintf(os.Stderr, "error occurred while initializing service: %s", err)
}
})
rootCmd.PersistentFlags().StringVarP(&conf.ConfigFile, "config", "c", "", "config file")
rootCmd.PersistentFlags().StringVarP(&conf.WorkDir, "work-dir", "p", ".", "current work directory")
rootCmd.PersistentFlags().BoolVarP(&forceStart, "force", "f", false, "force start manager-api")
rootCmd.AddCommand(
newVersionCommand(),
newInstallCommand(),
newRemoveCommand(),
newStartCommand(),
newStopCommand(),
newStatusCommand(),
)
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
_, _ = fmt.Fprintln(os.Stderr, err.Error())
_, _ = fmt.Fprintln(os.Stderr, err)
}
}
@ -75,9 +57,7 @@ func manageAPI() error {
conf.InitConf()
log.InitLogger()
s, err := server.NewServer(&server.Options{
ForceStart: forceStart,
})
s, err := server.NewServer(&server.Options{})
if err != nil {
return err
}
@ -94,7 +74,7 @@ func manageAPI() error {
case sig := <-quit:
log.Infof("The Manager API server receive %s and start shutting down", sig.String())
s.Stop()
log.Infof("The Manager API server exited")
log.Infof("See you next time!")
case err := <-errSig:
log.Errorf("The Manager API server start failed: %s", err.Error())
return err

View File

@ -1,94 +0,0 @@
/*
* 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 cmd
import (
"os"
"runtime"
"github.com/takama/daemon"
"github.com/apisix/manager-api/internal/conf"
)
type Service struct {
daemon.Daemon
}
var serviceState struct {
startService bool
stopService bool
installService bool
removeService bool
status bool
}
func createService() (*Service, error) {
var d daemon.Daemon
var err error
if runtime.GOOS == "darwin" {
d, err = daemon.New("apisix-dashboard", "Apache APISIX Dashboard", daemon.GlobalDaemon)
} else {
d, err = daemon.New("apisix-dashboard", "Apache APISIX Dashboard", daemon.SystemDaemon)
}
if err != nil {
return nil, err
}
service := &Service{d}
return service, nil
}
func (service *Service) manageService() (string, error) {
if serviceState.status {
return service.Status()
}
if serviceState.removeService {
return service.Remove()
}
if conf.WorkDir == "." {
dir, err := os.Getwd()
if err != nil {
return "proceed with --work-dir flag", err
}
conf.WorkDir = dir
}
if serviceState.installService {
return service.Install("-p", conf.WorkDir)
}
if serviceState.startService {
iStatus, err := service.Install("-p", conf.WorkDir)
if err != nil {
if err != daemon.ErrAlreadyInstalled {
return iStatus, err
}
iStatus = ""
}
sStatus, err := service.Start()
if iStatus != "" {
sStatus = iStatus + "\n" + sStatus
}
return sStatus, err
} else if serviceState.stopService {
return service.Stop()
}
err := manageAPI()
if err != nil {
return "Unable to start Manager API", err
}
return "The Manager API server exited", nil
}

View File

@ -1,36 +0,0 @@
/*
* 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 cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func newStartCommand() *cobra.Command {
return &cobra.Command{
Use: "start",
Short: "start Apache APISIX Dashboard service",
RunE: func(cmd *cobra.Command, args []string) error {
serviceState.startService = true
status, err := service.manageService()
fmt.Println(status)
return err
},
}
}

View File

@ -1,36 +0,0 @@
/*
* 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 cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func newStatusCommand() *cobra.Command {
return &cobra.Command{
Use: "status",
Short: "inspect the status of Apache APISIX Dashboard service",
RunE: func(cmd *cobra.Command, args []string) error {
serviceState.status = true
status, err := service.manageService()
fmt.Println(status)
return err
},
}
}

View File

@ -1,54 +0,0 @@
/*
* 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 cmd
import (
"fmt"
"os"
"syscall"
"github.com/spf13/cobra"
"github.com/apisix/manager-api/internal/conf"
"github.com/apisix/manager-api/internal/utils"
)
func newStopCommand() *cobra.Command {
return &cobra.Command{
Use: "stop",
Short: "stop Apache APISIX Dashboard service/program",
Run: func(cmd *cobra.Command, args []string) {
pid, err := utils.ReadPID(conf.PIDPath)
if err != nil {
if syscall.ENOENT.Error() != err.Error() {
fmt.Fprintf(os.Stderr, "failed to get manager-api pid: %s\n", err)
} else {
fmt.Fprintf(os.Stderr, "pid path %s not found, is manager-api running?\n", conf.PIDPath)
}
return
}
p, err := os.FindProcess(pid)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to find process manager-api: %s\n", err)
return
}
if err := p.Signal(syscall.SIGINT); err != nil {
fmt.Fprintf(os.Stderr, "failed to kill manager-api: %s", err)
}
},
}
}

View File

@ -59,7 +59,6 @@ var (
AuthConf Authentication
SSLDefaultStatus = 1 //enable ssl by default
ImportSizeLimit = 10 * 1024 * 1024
PIDPath = "/tmp/manager-api.pid"
AllowList []string
Plugins = map[string]bool{}
)

View File

@ -35,9 +35,7 @@ type server struct {
options *Options
}
type Options struct {
ForceStart bool // force start new instance
}
type Options struct {}
// NewServer Create a server manager
func NewServer(options *Options) (*server, error) {
@ -52,13 +50,6 @@ func (s *server) Start(errSig chan error) {
return
}
// write daemon pid file
err = s.writePID()
if err != nil {
errSig <- err
return
}
// print server info to stdout
s.printInfo()
@ -104,22 +95,6 @@ func (s *server) init() error {
return nil
}
func (s *server) writePID() error {
if err := utils.WritePID(conf.PIDPath, s.options.ForceStart); err != nil {
log.Errorf("failed to write pid: %s", err)
return err
}
utils.AppendToClosers(func() error {
if err := os.Remove(conf.PIDPath); err != nil {
log.Errorf("failed to remove pid path: %s", err)
return err
}
return nil
})
return nil
}
func (s *server) shutdownServer(server *http.Server) {
if server != nil {
ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second)

View File

@ -0,0 +1,8 @@
[Unit]
Description=apisix-dashboard
Conflicts=apisix-dashboard.service
After=network-online.target
[Service]
WorkingDirectory=/usr/local/apisix-dashboard
ExecStart=/usr/local/apisix-dashboard/manager-api -c /usr/local/apisix-dashboard/conf/conf.yaml

955
api/test/shell/cli_test.sh Executable file → Normal file
View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/usr/bin/env bats
#
# Licensed to the Apache Software Foundation (ASF) under one or more
@ -17,563 +17,422 @@
# limitations under the License.
#
set -ex
# !!!NOTICE!!!
# Try to run cli tests (such as virtual machines) in an isolated environment.
# This test will register the systemd service and run the test. Although
# environmental cleaning will eventually be running, it may still pollute
# your environment.
#
# For developers who have not modified the CLI part of the program, you do
# not need to run this test locally, but rely on the test results of GitHub
# workflow. If you have any improvement suggestions for this test case, you
# are welcome to submit a PR for modification.
VERSION=$(cat ./VERSION)
KERNEL=$(uname -s)
CONF_FILE="/usr/local/apisix-dashboard/conf/conf.yaml"
LOG_FILE="/usr/local/apisix-dashboard/logs/error.log"
ACCESS_LOG_FILE="/usr/local/apisix-dashboard/logs/access.log"
SERVICE_NAME="apisix-dashboard"
# test content in .githash
if [[ -f ../.githash ]]; then
GITHASH=$(cat ../.githash)
if [[ ! $GITHASH =~ ^[a-z0-9]{7}$ ]]; then
echo "failed: verify .githash content failed"
exit 1
fi
GITHASH=$(cat ../.githash)
if [[ ! $GITHASH =~ ^[a-z0-9]{7}$ ]]; then
echo "failed: verify .githash content failed"
exit 1
fi
else
GITHASH=$(HASH="ref: HEAD"; while [[ $HASH == ref\:* ]]; do HASH="$(cat "../.git/$(echo $HASH | cut -d \ -f 2)")"; done; echo ${HASH:0:7})
GITHASH=$(HASH="ref: HEAD"; while [[ $HASH == ref\:* ]]; do HASH="$(cat "../.git/$(echo $HASH | cut -d \ -f 2)")"; done; echo ${HASH:0:7})
fi
clean_up() {
git checkout conf/conf.yaml
recover_conf() {
run cp -rf ./conf/conf.yaml ${CONF_FILE}
[ "$status" -eq 0 ]
}
logfile="./logs/error.log"
check_logfile() {
if [[ ! -f $logfile ]]; then
echo "failed: failed to write log"
exit 1
fi
[ -f $LOG_FILE ]
}
clean_logfile() {
echo > $logfile
echo > $LOG_FILE
}
trap clean_up EXIT
export GO111MODULE=on
go build -o ./manager-api -ldflags "-X github.com/apisix/manager-api/internal/utils.version=${VERSION} -X github.com/apisix/manager-api/internal/utils.gitHash=${GITHASH}" ./main.go
# default level: warn, path: logs/error.log
./manager-api &
sleep 3
./manager-api stop
sleep 6
check_logfile
if [[ `grep -c "INFO" ${logfile}` -ne '0' ]]; then
echo "failed: should not write info log when level is warn"
exit 1
fi
clean_logfile
# change level and test signal
if [[ $KERNEL = "Darwin" ]]; then
sed -i "" 's/level: warn/level: info/' conf/conf.yaml
else
sed -i 's/level: warn/level: info/' conf/conf.yaml
fi
./manager-api &>/dev/null &
sleep 3
./manager-api stop
sleep 6
check_logfile
if [[ `ps -ef | grep "[m]anager-api" -c` -eq '1' ]]; then
echo "failed: the manager server didn't deal with signal in correct way"
exit 1
fi
if [[ `grep -c "server receive interrupt" ${logfile}` -ne '1' ]]; then
echo "failed: the manager server didn't deal with signal in correct way"
exit 1
fi
clean_logfile
# change path
if [[ $KERNEL = "Darwin" ]]; then
sed -i "" 's/logs\/error.log/.\/error.log/' conf/conf.yaml
else
sed -i 's/logs\/error.log/.\/error.log/' conf/conf.yaml
fi
./manager-api &
sleep 3
./manager-api stop
sleep 6
check_logfile
if [[ `grep -c "INFO" ./error.log` -eq '0' ]]; then
echo "failed: failed to write log on right level"
exit 1
fi
# run on a different path
workDir=$(pwd)
rm -rf html
mkdir html
cd html
echo "hi~" >> index.html
APISIX_API_WORKDIR=$workDir $workDir/manager-api &
sleep 5
res=$(curl http://127.0.0.1:9000)
$workDir/manager-api stop
sleep 6
cd -
rm -rf html
if [[ $res != "hi~" ]]; then
echo "failed: manager-api can't run on a different path"
exit 1
fi
clean_up
# run with -p flag out of the default directory
workDir=$(pwd)
distDir=/tmp/manager-api
cp -r $workDir $distDir
cd $distDir && rm -rf bin && mkdir bin && mv ./manager-api ./bin/
cd $distDir && rm -rf html && mkdir html && echo "hi~" >> html/index.html
cd $distDir/bin && ./manager-api -p $distDir &
sleep 5
res=$(curl http://127.0.0.1:9000)
$distDir/bin/manager-api stop
sleep 6
rm -fr $distDir
if [[ $res != "hi~" ]]; then
echo "failed: manager-api can't run with -p flag out of the default directory"
exit 1
fi
cd $workDir && git checkout conf/conf.yaml
# test start info
LOGLEVEL=$(cat conf/conf.yaml | awk '$1=="level:"{print $2}')
HOST=$(cat conf/conf.yaml | awk '$1=="host:"{print $2}')
PORT=$(cat conf/conf.yaml | awk '$1=="port:"{print $2}')
STDOUT=/tmp/manager-api
./manager-api &> ${STDOUT} &
sleep 3
./manager-api stop
sleep 6
if [[ `grep -c "The manager-api is running successfully\!" ${STDOUT}` -ne '1' ]]; then
echo "failed: the manager server didn't show started info"
exit 1
fi
if [[ `grep -c -w "${VERSION}" ${STDOUT}` -ne '1' ]]; then
echo "failed: the manager server didn't show started info"
exit 1
fi
if [[ `grep -c "${GITHASH}" ${STDOUT}` -ne '1' ]]; then
echo "failed: the manager server didn't show started info"
exit 1
fi
if [[ `grep -c "${LOGLEVEL}" ${STDOUT}` -ne '1' ]]; then
echo "failed: the manager server didn't show started info"
exit 1
fi
if [[ `grep -c "0.0.0.0:${PORT}" ${STDOUT}` -ne '1' ]]; then
echo "failed: the manager server didn't show started info"
exit 1
fi
# test version command
out=$(./manager-api version 2>&1 || true)
if [[ `echo $out | grep -c $VERSION` -ne '1' ]]; then
echo "failed: the manager server didn't show version info"
exit 1
fi
if [[ `echo $out | grep -c $GITHASH` -ne '1' ]]; then
echo "failed: the manager server didn't show git hash info"
exit 1
fi
# set an invalid etcd endpoint
clean_up
if [[ $KERNEL = "Darwin" ]]; then
sed -i "" 's/127.0.0.1:2379/127.0.0.0:2379/' conf/conf.yaml
else
sed -i 's/127.0.0.1:2379/127.0.0.0:2379/' conf/conf.yaml
fi
./manager-api > output.log 2>&1 &
sleep 6
cat ${logfile}
if [[ `grep -c "server/store.go" ${logfile}` -ne '1' ]]; then
echo "failed: failed to write the correct caller"
exit 1
fi
./manager-api stop
sleep 6
# clean config
clean_up
# access log test
./manager-api &
sleep 3
curl http://127.0.0.1:9000/apisix/admin/user/login -H "Content-Type: application/json" -d '{"username":"admin", "password": "admin"}'
./manager-api stop
sleep 6
if [[ `grep -c "/apisix/admin/user/login" ./logs/access.log` -eq '0' ]]; then
echo "failed: failed to write access log"
exit 1
fi
# clean config
clean_up
# set ip allowed list
if [[ $KERNEL = "Darwin" ]]; then
sed -i "" 's@- 127.0.0.1 @- 10.0.0.1 @' conf/conf.yaml
else
sed -i 's@- 127.0.0.1 @- 10.0.0.1 @' conf/conf.yaml
fi
./manager-api &
sleep 3
# should be forbidden
curl http://127.0.0.1:9000
code=$(curl -k -i -m 20 -o /dev/null -s -w %{http_code} http://127.0.0.1:9000)
if [ ! $code -eq 403 ]; then
echo "failed: verify IP allowed list failed"
exit 1
fi
./manager-api stop
sleep 6
clean_up
# HTTPS test
currentDir=$(pwd)
if [[ $KERNEL = "Darwin" ]]; then
sed -i "" 's@# ssl:@ssl:@' conf/conf.yaml
sed -i "" 's@# port: 9001@ port: 9001@' conf/conf.yaml
sed -i "" "s@# cert: \"/tmp/cert/example.crt\"@ cert: \"$currentDir/test/certs/test2.crt\"@" conf/conf.yaml
sed -i "" "s@# key: \"/tmp/cert/example.key\"@ cert: \"$currentDir/test/certs/test2.key\"@" conf/conf.yaml
else
sed -i 's@# ssl:@ssl:@' conf/conf.yaml
sed -i 's@# port: 9001@ port: 9001@' conf/conf.yaml
sed -i "s@# cert: \"/tmp/cert/example.crt\"@ cert: \"$currentDir/test/certs/test2.crt\"@" conf/conf.yaml
sed -i "s@# key: \"/tmp/cert/example.key\"@ key: \"$currentDir/test/certs/test2.key\"@" conf/conf.yaml
fi
./manager-api &
sleep 3
# access by HTTPS
code=$(curl -k -i -m 20 -o /dev/null -s -w %{http_code} --resolve 'www.test2.com:9001:127.0.0.1' https://www.test2.com:9001/apisix/admin/tool/version)
if [ ! $code -eq 200 ]; then
echo "failed: verify HTTPS failed"
exit 1
fi
./manager-api stop
sleep 6
clean_up
# etcd basic auth
# add root user
curl -L http://localhost:2379/v3/auth/user/add -d '{"name": "root", "password": "root"}'
# add root role
curl -L http://localhost:2379/v3/auth/role/add -d '{"name": "root"}'
# grant root role to root user
curl -L http://localhost:2379/v3/auth/user/grant -d '{"user": "root", "role": "root"}'
# enable auth
curl -L http://localhost:2379/v3/auth/enable -d '{}'
./manager-api &
sleep 3
# make sure it's wrong
if [[ `grep -c "etcdserver: user name is empty" ${logfile}` -eq '0' ]]; then
echo "failed: failed to validate etcd basic auth"
exit 1
fi
./manager-api stop
sleep 6
# modify etcd auth config
if [[ $KERNEL = "Darwin" ]]; then
sed -i "" '1,$s/# username: "root" # ignore etcd username if not enable etcd auth/username: "root"/g' conf/conf.yaml
sed -i "" '1,$s/# password: "123456" # ignore etcd password if not enable etcd auth/password: "root"/g' conf/conf.yaml
else
sed -i '1,$s/# username: "root" # ignore etcd username if not enable etcd auth/username: "root"/g' conf/conf.yaml
sed -i '1,$s/# password: "123456" # ignore etcd password if not enable etcd auth/password: "root"/g' conf/conf.yaml
fi
./manager-api &
sleep 3
# validate process is right by requesting login api
resp=$(curl http://127.0.0.1:9000/apisix/admin/user/login -H "Content-Type: application/json" -d '{"username":"admin", "password": "admin"}')
token=$(echo "${resp}" | sed 's/{/\n/g' | sed 's/,/\n/g' | grep "token" | sed 's/:/\n/g' | sed '1d' | sed 's/}//g' | sed 's/"//g')
if [ -z "${token}" ]; then
echo "login failed"
exit 1
fi
# more validation to make sure it's ok to access etcd
resp=$(curl -ig -XPUT http://127.0.0.1:9000/apisix/admin/consumers -i -H "Content-Type: application/json" -H "Authorization: $token" -d '{"username":"etcd_basic_auth_test"}')
respCode=$(echo "${resp}" | sed 's/{/\n/g'| sed 's/,/\n/g' | grep "code" | sed 's/:/\n/g' | sed '1d')
respMessage=$(echo "${resp}" | sed 's/{/\n/g'| sed 's/,/\n/g' | grep "message" | sed 's/:/\n/g' | sed '1d')
if [ "$respCode" != "0" ] || [ $respMessage != "\"\"" ]; then
echo "verify access etcd failed"
exit 1
fi
# check the version api
resp=$(curl http://127.0.0.1:9000/apisix/admin/tool/version)
if [[ `echo ${resp} | grep -c "${VERSION}"` -ne '1' ]]; then
echo "failed: can't through api to get version info"
exit 1
fi
if [[ `echo ${resp} | grep -c "${GITHASH}"` -ne '1' ]]; then
echo "failed: can't through api to get githash info"
exit 1
fi
check_logfile
./manager-api stop
sleep 6
clean_up
# etcd prefix test
# disable etcd authentication
resp=$(curl -L http://localhost:2379/v3/auth/authenticate -X POST -d '{"name": "root", "password": "root"}')
etcd_token=$(echo ${resp}|grep -oE "token\".*\"(.*)\""|awk -F[:\"] '{print $4}')
if [ -z "${etcd_token}" ]; then
echo "authenticate failed"
exit 1
fi
curl -L http://localhost:2379/v3/auth/disable -H "Authorization: ${etcd_token}" -X POST -d ''
./manager-api &
sleep 3
resp=$(curl http://127.0.0.1:9000/apisix/admin/user/login -H "Content-Type: application/json" -d '{"username":"admin", "password": "admin"}')
token=$(echo "${resp}" | sed 's/{/\n/g' | sed 's/,/\n/g' | grep "token" | sed 's/:/\n/g' | sed '1d' | sed 's/}//g' | sed 's/"//g')
if [ -z "${token}" ]; then
echo "login failed"
exit 1
fi
# default etcd prefix value /apisix
prefix=/apisix
# add consumer by manager-api
resp=$(curl -ig -XPUT http://127.0.0.1:9000/apisix/admin/consumers -i -H "Content-Type: application/json" -H "Authorization: $token" -d '{"username":"etcd_prefix_test"}')
# get consumer by etcd v3 api
key_base64=`echo -n $prefix/consumers/etcd_prefix_test | base64`
resp=$(curl -L http://localhost:2379/v3/kv/range -X POST -d '{"key": "'"${key_base64}"'"}')
count=`echo $resp | grep -oE "count.*([0-9]+)" | awk -F\" '{print $3}'`
if [ ! $count ] || [ $count -ne 1 ]; then
echo "consumer failed"
exit 1
fi
./manager-api stop
sleep 6
clean_up
# modify etcd prefix config to /apisix-test
if [[ $KERNEL = "Darwin" ]]; then
sed -i "" '1,$s/# prefix: \/apisix.*/prefix: \/apisix-test/g' conf/conf.yaml
else
sed -i '1,$s/# prefix: \/apisix.*/prefix: \/apisix-test/g' conf/conf.yaml
fi
./manager-api &
sleep 3
resp=$(curl http://127.0.0.1:9000/apisix/admin/user/login -H "Content-Type: application/json" -d '{"username":"admin", "password": "admin"}')
token=$(echo "${resp}" | sed 's/{/\n/g' | sed 's/,/\n/g' | grep "token" | sed 's/:/\n/g' | sed '1d' | sed 's/}//g' | sed 's/"//g')
if [ -z "${token}" ]; then
echo "login failed"
exit 1
fi
# modified etcd prefix value /apisix-test
prefix=/apisix-test
# add consumer by manager-api
resp=$(curl -ig -XPUT http://127.0.0.1:9000/apisix/admin/consumers -i -H "Content-Type: application/json" -H "Authorization: $token" -d '{"username":"etcd_prefix_test"}')
# get consumer by etcd v3 api
key_base64=`echo -n $prefix/consumers/etcd_prefix_test | base64`
resp=$(curl -L http://localhost:2379/v3/kv/range -X POST -d '{"key": "'"${key_base64}"'"}')
count=`echo $resp | grep -oE "count.*([0-9]+)" | awk -F\" '{print $3}'`
if [ ! $count ] || [ $count -ne 1 ]; then
echo "consumer failed"
exit 1
fi
./manager-api stop
sleep 6
clean_up
# mtls test
./etcd-v3.4.14-linux-amd64/etcd --name infra0 --data-dir infra0 \
--client-cert-auth --trusted-ca-file=$(pwd)/test/certs/mtls_ca.pem --cert-file=$(pwd)/test/certs/mtls_server.pem --key-file=$(pwd)/test/certs/mtls_server-key.pem \
--advertise-client-urls https://127.0.0.1:3379 --listen-client-urls https://127.0.0.1:3379 --listen-peer-urls http://127.0.0.1:3380 &
currentDir=$(pwd)
if [[ $KERNEL = "Darwin" ]]; then
sed -i "" "s@key_file: \"\"@key_file: \"$currentDir/test/certs/mtls_client-key.pem\"@g" conf/conf.yaml
sed -i "" "s@cert_file: \"\"@cert_file: \"$currentDir/test/certs/mtls_client.pem\"@g" conf/conf.yaml
sed -i "" "s@ca_file: \"\"@ca_file: \"$currentDir/test/certs/mtls_ca.pem\"@g" conf/conf.yaml
sed -i "" 's/127.0.0.1:2379/127.0.0.1:3379/' conf/conf.yaml
else
sed -i "s@key_file: \"\"@key_file: \"$currentDir/test/certs/mtls_client-key.pem\"@g" conf/conf.yaml
sed -i "s@cert_file: \"\"@cert_file: \"$currentDir/test/certs/mtls_client.pem\"@g" conf/conf.yaml
sed -i "s@ca_file: \"\"@ca_file: \"$currentDir/test/certs/mtls_ca.pem\"@g" conf/conf.yaml
sed -i 's/127.0.0.1:2379/127.0.0.1:3379/' conf/conf.yaml
fi
./manager-api &
sleep 3
# validate process is right by requesting login api
resp=$(curl http://127.0.0.1:9000/apisix/admin/user/login -H "Content-Type: application/json" -d '{"username":"admin", "password": "admin"}')
token=$(echo "${resp}" | sed 's/{/\n/g' | sed 's/,/\n/g' | grep "token" | sed 's/:/\n/g' | sed '1d' | sed 's/}//g' | sed 's/"//g')
if [ -z "${token}" ]; then
echo "login failed(mTLS connect to ETCD)"
exit 1
fi
# more validation to make sure it's ok to access etcd
resp=$(curl -ig -XPUT http://127.0.0.1:9000/apisix/admin/consumers -i -H "Content-Type: application/json" -H "Authorization: $token" -d '{"username":"etcd_basic_auth_test"}')
respCode=$(echo "${resp}" | sed 's/{/\n/g'| sed 's/,/\n/g' | grep "code" | sed 's/:/\n/g' | sed '1d')
respMessage=$(echo "${resp}" | sed 's/{/\n/g'| sed 's/,/\n/g' | grep "message" | sed 's/:/\n/g' | sed '1d')
if [ "$respCode" != "0" ] || [ $respMessage != "\"\"" ]; then
echo "verify writing data failed(mTLS connect to ETCD)"
exit 1
fi
./manager-api stop
sleep 6
clean_up
# run manager api as os service
# 2 times OK for installing and starting
if [[ `echo $(sudo ./manager-api start) | grep -o "OK" | wc -l` -ne "2" ]]; then
echo "error while initializing the service"
exit 1
fi
# check running status
if [[ `echo $(sudo ./manager-api status) | grep -c "running..."` -ne "1" ]]; then
echo "error while starting the service"
exit 1
fi
# stop the service
sudo ./manager-api stop
sleep 2
# recheck running status
if [[ `echo $(sudo ./manager-api status) | grep -c "Service is stopped"` -ne "1" ]]; then
echo "error while stopping the service"
exit 1
fi
# restart the service
# 1 time OK for just for starting
if [[ `echo $(sudo ./manager-api start) | grep -c "OK"` -ne "1" ]]; then
echo "error while restarting the service"
exit 1
fi
# stop the service
sudo ./manager-api stop
sleep 2
# remove the service
if [[ `echo $(sudo ./manager-api remove) | grep -c "OK"` -ne "1" ]]; then
echo "error while removing the service"
exit 1
fi
# test manager-api output for bad data on etcd
# make a dummy entry
./etcd-v3.4.14-linux-amd64/etcdctl put /apisix/routes/unique1 "{\"id\":}"
sleep 2
./manager-api 2>man-api.err &
sleep 4
if [[ `cat man-api.err | grep -c "Error occurred while initializing logical store: /apisix/routes"` -ne '1' ||
`cat man-api.err | grep -c "Error: json unmarshal failed"` -ne '1' ]];then
echo "manager api failed to stream error on stderr for bad data"
exit 1
fi
# delete dummy entry
./etcd-v3.4.14-linux-amd64/etcdctl del /apisix/routes/unique1
# just to make sure
./manager-api stop
sleep 6
clean_up
# run manager api as os service
# 2 times OK for installing and starting
if [[ `echo $(sudo ./manager-api start) | grep -o "OK" | wc -l` -ne "2" ]]; then
echo "error while initializing the service"
exit 1
fi
# check running status
if [[ `echo $(sudo ./manager-api status) | grep -c "running..."` -ne "1" ]]; then
echo "error while starting the service"
exit 1
fi
# stop the service
sudo ./manager-api stop
sleep 2
# recheck running status
if [[ `echo $(sudo ./manager-api status) | grep -c "Service is stopped"` -ne "1" ]]; then
echo "error while stopping the service"
exit 1
fi
# restart the service
# 1 time OK for just for starting
if [[ `echo $(sudo ./manager-api start) | grep -c "OK"` -ne "1" ]]; then
echo "error while restarting the service"
exit 1
fi
# stop the service
sudo ./manager-api stop
sleep 2
# remove the service
if [[ `echo $(sudo ./manager-api remove) | grep -c "OK"` -ne "1" ]]; then
echo "error while removing the service"
exit 1
fi
pkill -f etcd
clean_up
start_dashboard() {
run systemctl start ${SERVICE_NAME}
[ "$status" -eq 0 ]
sleep $1
}
stop_dashboard() {
run systemctl stop ${SERVICE_NAME}
[ "$status" -eq 0 ]
sleep $1
}
### Test Case
#pre
@test "Build and Deploy APISIX Dashboard Manager API" {
run go build -o ./manager-api -ldflags "-X github.com/apisix/manager-api/internal/utils.version=${VERSION} -X github.com/apisix/manager-api/internal/utils.gitHash=${GITHASH}" ./main.go
[ "$status" -eq 0 ]
# prepare service files
mkdir -p /usr/local/apisix-dashboard/conf /usr/local/apisix-dashboard/logs
cp ./conf/* /usr/local/apisix-dashboard/conf
cp ./manager-api /usr/local/apisix-dashboard
# create systemd service
cp ./service/apisix-dashboard.service /usr/lib/systemd/system/${SERVICE_NAME}.service
run systemctl daemon-reload
[ "$status" -eq 0 ]
}
#1
@test "Check warn log level" {
start_dashboard 3
stop_dashboard 6
check_logfile
[ $(grep -c "INFO" "${LOG_FILE}") -eq '0' ]
clean_logfile
}
#2
@test "Check info log leve and signal" {
if [[ $KERNEL = "Darwin" ]]; then
sed -i "" 's/level: warn/level: info/' ${CONF_FILE}
else
sed -i 's/level: warn/level: info/' ${CONF_FILE}
fi
start_dashboard 3
stop_dashboard 6
check_logfile
[ $(grep -c "server receive terminated" "${LOG_FILE}") -eq '1' ]
clean_logfile
}
#3
@test "Check start info" {
LOGLEVEL=$(cat "$CONF_FILE" | awk '$1=="level:"{print $2}')
HOST=$(cat "$CONF_FILE" | awk '$1=="host:"{print $2}')
PORT=$(cat "$CONF_FILE" | awk '$1=="port:"{print $2}')
start_dashboard 3
run systemctl status ${SERVICE_NAME}
[ $(echo "$output" | grep -c "The manager-api is running successfully\!") -eq '1' ]
[ $(echo "$output" | grep -c -w "${VERSION}") -eq '1' ]
[ $(echo "$output" | grep -c "${GITHASH}") -eq '1' ]
[ $(echo "$output" | grep -c "${LOGLEVEL}") -eq '1' ]
[ $(echo "$output" | grep -c "${HOST}:${PORT}") -eq '1' ]
stop_dashboard 6
}
#4
@test "Check version sub-command" {
run /usr/local/apisix-dashboard/manager-api version
[ $(echo "$output" | grep -c "$VERSION") -eq '1' ]
[ $(echo "$output" | grep -c "$GITHASH") -eq '1' ]
}
#5
@test "Check static file server" {
# create html directory
mkdir -p /usr/local/apisix-dashboard/html
echo "hi~" >> /usr/local/apisix-dashboard/html/index.html
# start Manager API
start_dashboard 3
# request index page
result=$(curl "http://127.0.0.1:9000")
[ "$result" = "hi~" ]
stop_dashboard 6
recover_conf
}
#6
@test "Check invalid etcd endpoint" {
recover_conf
if [[ $KERNEL = "Darwin" ]]; then
sed -i "" 's/127.0.0.1:2379/127.0.0.0:2379/' ${CONF_FILE}
else
sed -i 's/127.0.0.1:2379/127.0.0.0:2379/' ${CONF_FILE}
fi
start_dashboard 6
run journalctl -u ${SERVICE_NAME}.service -n 30
[ $(echo "$output" | grep -c "Error while dialing dial tcp") -eq '1' ]
stop_dashboard 6
}
#7
@test "Check assess log" {
recover_conf
start_dashboard 3
run curl http://127.0.0.1:9000/apisix/admin/user/login -H "Content-Type: application/json" -d '{"username":"admin", "password": "admin"}'
[ "$status" -eq 0 ]
stop_dashboard 6
[ $(grep -c "/apisix/admin/user/login" "${ACCESS_LOG_FILE}") -ne '0' ]
}
#8
@test "Check ip allow list" {
recover_conf
if [[ $KERNEL = "Darwin" ]]; then
sed -i "" 's@- 127.0.0.1 @- 10.0.0.1 @' ${CONF_FILE}
else
sed -i 's@- 127.0.0.1 @- 10.0.0.1 @' ${CONF_FILE}
fi
start_dashboard 3
run curl -k -i -m 20 -o /dev/null -s -w %{http_code} "http://127.0.0.1:9000"
[ "$output" -eq 403 ]
stop_dashboard 6
}
#9
@test "Check HTTPS server" {
recover_conf
if [[ $KERNEL = "Darwin" ]]; then
sed -i "" 's@# ssl:@ssl:@' ${CONF_FILE}
sed -i "" 's@# port: 9001@ port: 9001@' ${CONF_FILE}
sed -i "" "s@# cert: \"/tmp/cert/example.crt\"@ cert: \"$(pwd)/test/certs/test2.crt\"@" ${CONF_FILE}
sed -i "" "s@# key: \"/tmp/cert/example.key\"@ cert: \"$(pwd)/test/certs/test2.key\"@" ${CONF_FILE}
else
sed -i 's@# ssl:@ssl:@' ${CONF_FILE}
sed -i 's@# port: 9001@ port: 9001@' ${CONF_FILE}
sed -i "s@# cert: \"/tmp/cert/example.crt\"@ cert: \"$(pwd)/test/certs/test2.crt\"@" ${CONF_FILE}
sed -i "s@# key: \"/tmp/cert/example.key\"@ key: \"$(pwd)/test/certs/test2.key\"@" ${CONF_FILE}
fi
start_dashboard 3
run curl -k -i -m 20 -o /dev/null -s -w %{http_code} --resolve 'www.test2.com:9001:127.0.0.1' "https://www.test2.com:9001/apisix/admin/tool/version"
[ "$output" -eq 200 ]
stop_dashboard 6
}
#10
@test "Check etcd basic auth" {
recover_conf
# add root user
curl -L http://localhost:2379/v3/auth/user/add -d '{"name": "root", "password": "root"}'
# add root role
curl -L http://localhost:2379/v3/auth/role/add -d '{"name": "root"}'
# grant root role to root user
curl -L http://localhost:2379/v3/auth/user/grant -d '{"user": "root", "role": "root"}'
# enable auth
curl -L http://localhost:2379/v3/auth/enable -d '{}'
start_dashboard 3
[ $(grep -c "etcdserver: user name is empty" ${LOG_FILE}) -ne '0' ]
stop_dashboard 6
# modify etcd auth config
if [[ $KERNEL = "Darwin" ]]; then
sed -i "" '1,$s/# username: "root" # ignore etcd username if not enable etcd auth/username: "root"/g' ${CONF_FILE}
sed -i "" '1,$s/# password: "123456" # ignore etcd password if not enable etcd auth/password: "root"/g' ${CONF_FILE}
else
sed -i '1,$s/# username: "root" # ignore etcd username if not enable etcd auth/username: "root"/g' ${CONF_FILE}
sed -i '1,$s/# password: "123456" # ignore etcd password if not enable etcd auth/password: "root"/g' ${CONF_FILE}
fi
start_dashboard 3
# validate process is right by requesting login api
run curl http://127.0.0.1:9000/apisix/admin/user/login -H "Content-Type: application/json" -d '{"username":"admin", "password": "admin"}'
token=$(echo "$output" | sed 's/{/\n/g' | sed 's/,/\n/g' | grep "token" | sed 's/:/\n/g' | sed '1d' | sed 's/}//g' | sed 's/"//g')
[ -n "${token}" ]
# more validation to make sure it's ok to access etcd
run curl -ig -XPUT http://127.0.0.1:9000/apisix/admin/consumers -i -H "Content-Type: application/json" -H "Authorization: $token" -d '{"username":"etcd_basic_auth_test"}'
respCode=$(echo "$output" | sed 's/{/\n/g'| sed 's/,/\n/g' | grep "code" | sed 's/:/\n/g' | sed '1d')
respMessage=$(echo "$output" | sed 's/{/\n/g'| sed 's/,/\n/g' | grep "message" | sed 's/:/\n/g' | sed '1d')
[ "$respCode" = "0" ]
[ "$respMessage" = "\"\"" ]
run curl "http://127.0.0.1:9000/apisix/admin/tool/version"
[ $(echo "$output" | grep -c "${VERSION}") -eq '1' ]
[ $(echo "$output" | grep -c "${GITHASH}") -eq '1' ]
check_logfile
stop_dashboard 6
# disable etcd basic auth
run curl -L http://localhost:2379/v3/auth/authenticate -X POST -d '{"name": "root", "password": "root"}'
etcd_token=$(echo "$output" |grep -oE "token\".*\"(.*)\""|awk -F[:\"] '{print $4}')
[ -n "${etcd_token}" ]
run curl -L http://localhost:2379/v3/auth/disable -H "Authorization: ${etcd_token}" -X POST -d ''
[ "$status" -eq 0 ]
}
#11
@test "Check etcd prefix" {
recover_conf
start_dashboard 3
run curl http://127.0.0.1:9000/apisix/admin/user/login -H "Content-Type: application/json" -d '{"username":"admin", "password": "admin"}'
[ "$status" -eq 0 ]
token=$(echo "$output" | sed 's/{/\n/g' | sed 's/,/\n/g' | grep "token" | sed 's/:/\n/g' | sed '1d' | sed 's/}//g' | sed 's/"//g')
[ -n "${token}" ]
prefix="/apisix"
key_base64=$(echo -n $prefix/consumers/etcd_prefix_test | base64)
run curl -ig -XPUT http://127.0.0.1:9000/apisix/admin/consumers -i -H "Content-Type: application/json" -H "Authorization: $token" -d '{"username":"etcd_prefix_test"}'
[ "$status" -eq 0 ]
run curl -L http://localhost:2379/v3/kv/range -X POST -d '{"key": "'"${key_base64}"'"}'
[ "$status" -eq 0 ]
count=$(echo "$output" | grep -oE "count.*([0-9]+)" | awk -F\" '{print $3}')
[ "$count" ]
[ "$count" -eq 1 ]
stop_dashboard 6
recover_conf
# modify etcd prefix config to /apisix-test
if [[ $KERNEL = "Darwin" ]]; then
sed -i "" '1,$s/# prefix: \/apisix.*/prefix: \/apisix-test/g' ${CONF_FILE}
else
sed -i '1,$s/# prefix: \/apisix.*/prefix: \/apisix-test/g' ${CONF_FILE}
fi
start_dashboard 3
run curl http://127.0.0.1:9000/apisix/admin/user/login -H "Content-Type: application/json" -d '{"username":"admin", "password": "admin"}'
[ "$status" -eq 0 ]
token=$(echo "$output" | sed 's/{/\n/g' | sed 's/,/\n/g' | grep "token" | sed 's/:/\n/g' | sed '1d' | sed 's/}//g' | sed 's/"//g')
[ -n "${token}" ]
prefix="/apisix-test"
key_base64=$(echo -n $prefix/consumers/etcd_prefix_test | base64)
run curl -ig -XPUT http://127.0.0.1:9000/apisix/admin/consumers -i -H "Content-Type: application/json" -H "Authorization: $token" -d '{"username":"etcd_prefix_test"}'
[ "$status" -eq 0 ]
run curl -L http://localhost:2379/v3/kv/range -X POST -d '{"key": "'"${key_base64}"'"}'
[ "$status" -eq 0 ]
count=$(echo "$output" | grep -oE "count.*([0-9]+)" | awk -F\" '{print $3}')
[ "$count" ]
[ "$count" -eq 1 ]
stop_dashboard 6
}
#12
@test "Check etcd mTLS" {
recover_conf
run ./etcd-v3.4.14-linux-amd64/etcd --name infra0 --data-dir infra0 \
--client-cert-auth --trusted-ca-file=$(pwd)/test/certs/mtls_ca.pem --cert-file=$(pwd)/test/certs/mtls_server.pem --key-file=$(pwd)/test/certs/mtls_server-key.pem \
--advertise-client-urls https://127.0.0.1:3379 --listen-client-urls https://127.0.0.1:3379 --listen-peer-urls http://127.0.0.1:3380 &
if [[ $KERNEL = "Darwin" ]]; then
sed -i "" "s@key_file: \"\"@key_file: \"$(pwd)/test/certs/mtls_client-key.pem\"@g" ${CONF_FILE}
sed -i "" "s@cert_file: \"\"@cert_file: \"$(pwd)/test/certs/mtls_client.pem\"@g" ${CONF_FILE}
sed -i "" "s@ca_file: \"\"@ca_file: \"$(pwd)/test/certs/mtls_ca.pem\"@g" ${CONF_FILE}
sed -i "" 's/127.0.0.1:2379/127.0.0.1:3379/' ${CONF_FILE}
else
sed -i "s@key_file: \"\"@key_file: \"$(pwd)/test/certs/mtls_client-key.pem\"@g" ${CONF_FILE}
sed -i "s@cert_file: \"\"@cert_file: \"$(pwd)/test/certs/mtls_client.pem\"@g" ${CONF_FILE}
sed -i "s@ca_file: \"\"@ca_file: \"$(pwd)/test/certs/mtls_ca.pem\"@g" ${CONF_FILE}
sed -i 's/127.0.0.1:2379/127.0.0.1:3379/' ${CONF_FILE}
fi
start_dashboard 3
run curl http://127.0.0.1:9000/apisix/admin/user/login -H "Content-Type: application/json" -d '{"username":"admin", "password": "admin"}'
[ "$status" -eq 0 ]
token=$(echo "$output" | sed 's/{/\n/g' | sed 's/,/\n/g' | grep "token" | sed 's/:/\n/g' | sed '1d' | sed 's/}//g' | sed 's/"//g')
[ -n "${token}" ]
run curl -ig -XPUT http://127.0.0.1:9000/apisix/admin/consumers -i -H "Content-Type: application/json" -H "Authorization: $token" -d '{"username":"etcd_mtls_test"}'
respCode=$(echo "$output" | sed 's/{/\n/g'| sed 's/,/\n/g' | grep "code" | sed 's/:/\n/g' | sed '1d')
respMessage=$(echo "$output" | sed 's/{/\n/g'| sed 's/,/\n/g' | grep "message" | sed 's/:/\n/g' | sed '1d')
[ "$respCode" = "0" ]
[ "$respMessage" = "\"\"" ]
stop_dashboard 6
}
#13
@test "Check etcd bad data" {
recover_conf
run ./etcd-v3.4.14-linux-amd64/etcdctl put /apisix/routes/unique1 "{\"id\":}"
[ "$status" -eq 0 ]
sleep 2
start_dashboard 3
run journalctl -u ${SERVICE_NAME}.service -n 30
[ $(echo "$output" | grep -c "Error occurred while initializing logical store: /apisix/routes") -eq '1' ]
[ $(echo "$output" | grep -c "Error: json unmarshal failed") -eq '1' ]
run ./etcd-v3.4.14-linux-amd64/etcdctl del /apisix/routes/unique1
[ "$status" -eq 0 ]
stop_dashboard 6
}
#post
@test "Clean test environment" {
# kill etcd
pkill -f etcd
# stop dashboard service
stop_dashboard 0
# clean configure and log files
rm -rf /usr/local/apisix-dashboard
rm /usr/lib/systemd/system/${SERVICE_NAME}.service
# reload systemd services
run systemctl daemon-reload
[ "$status" -eq 0 ]
}

View File

@ -9,7 +9,7 @@
{
"type": "category",
"label": "Installation",
"items": ["deploy", "deploy-with-docker", "deploy-with-rpm"]
"items": ["install", "deploy-with-docker"]
},
{
"type": "category",

View File

@ -1,5 +1,5 @@
---
title: Deploy with Docker
title: Rebuild Docker image
---
<!--

View File

@ -1,45 +0,0 @@
---
title: Deploy with RPM
---
<!--
#
# 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.
#
-->
**NOTE:** Only support CentOS 7 currently, for more information, please refer to [here](./deploy.md).
## Install from RPM
```sh
$ sudo yum install -y https://github.com/apache/apisix-dashboard/releases/download/v2.9.0/apisix-dashboard-2.9.0-0.el7.x86_64.rpm
```
## Run
Before you start, make sure the following dependencies are installed and running in your environment.
- [etcd](https://etcd.io/docs/v3.4.0/dl-build/) 3.4.0+
```sh
$ sudo nohup manager-api -p /usr/local/apisix/dashboard/ &
# or manager-api as a service
$ sudo manager-api start -p /usr/local/apisix/dashboard/
```
Without changing the configuration, visit `http://127.0.0.1:9000` to use the dashboard with GUI, where the default username and password are `admin`.

View File

@ -1,133 +0,0 @@
---
title: Deploy with Source Codes
---
<!--
#
# 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.
#
-->
The Dashboard contains both `manager-api` and `web`, but `web` is _optional_.
The `manager-api` and `web` will be included in this build guide product.
## Prerequisites
Before using source codes to build, make sure that the following dependencies are installed in your environment.
### manager-api
1. [Golang](https://golang.org/dl/) 1.13+: For users in mainland China, you can use the following command to speed up the module downloads.
```sh
$ go env -w GOPROXY=https://goproxy.cn,direct
```
### web
1. [Node.js](https://nodejs.org/en/download/) 10.23.0+
2. [Yarn](https://yarnpkg.com/getting-started/install)
## Clone the project
```sh
$ git clone -b release/2.9.0 https://github.com/apache/apisix-dashboard.git
```
## Build
```sh
$ cd apisix-dashboard
$ make build
```
When the build is complete, the results are stored in the root `output` directory.
Note: `make build` will build `manager-api` and `web`, use the `make help` command to see more commands.
## Launch
1. After the build is complete and before you start, make sure the following dependencies are installed and running in your environment.
- [etcd](https://etcd.io/docs/v3.4.0/dl-build/) 3.4.0+
2. Check and modify the configuration information in `output/conf/conf.yaml` according to your deployment environment.
3. Launch the Dashboard
```sh
$ cd ./output
$ ./manager-api
# or running in background
$ nohup ./manager-api &
```
4. Without changing the configuration, visit `http://127.0.0.1:9000` to use the dashboard with GUI, where the default username and password are `admin`.
5. Stop the Dashboard
`manager-api` provides a sub command `stop` to quit the program gracefully, just
run:
```sh
$ ./manager-api stop
```
### Optional
6. Running `manager-api` as an OS service.
Without clubbing `manager-api` with external command such as `nohup` (in Unix systems), we also provide a long term solution for running the program as an **operating system managed background service**. The feature is cross-platform, os agnostic and works on well known Linux, Windows and Mac OS distributions.
**Note:** The `manager-api` as a service is listed by the name `apisix-dashboard` under the OS's service manager.
`manager-api` provides a list of sub commands to start and manage the lifecycle of the background service.
```sh
# start Apache APISIX Dashboard service
$ ./manager-api start
# re-install Apache APISIX Dashboard service
$ ./manager-api install
# inspect the status of Apache APISIX Dashboard service
$ ./manager-api status
# stop Apache APISIX Dashboard service. stop can be used with or without service
$ ./manager-api stop
# remove Apache APISIX Dashboard service
$ ./manager-api remove
```
## Working directory
The `output` directory mention above is the default working directory.
You can move the entire directory to any path you want, and use the `-p` to specify it as the working directory.
For example, you can move it to `/usr/local/apisix-dashboard/`
```sh
$ mv ./output/manager-api /usr/local/bin/
$ mv ./output/ /usr/local/apisix-dashboard/
$ manager-api -p /usr/local/apisix-dashboard/
```

170
docs/en/latest/install.md Normal file
View File

@ -0,0 +1,170 @@
---
title: Basic Deploy
---
<!--
#
# 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.
#
-->
Installing Apache APISIX Dashboard on Linux is easy.
Now, we provide Docker image and RPM installation package.
## Docker {#docker}
We recommend using Docker to run Dashboard:
```shell
docker pull apache/apisix-dashboard
docker run -d --name dashboard \
-p 9000:9000 \
-v <CONFIG_FILE>:/usr/local/apisix-dashboard/conf/conf.yaml \
apache/apisix-dashboard
```
:::note
Please replace `<CONFIG_FILE>` to your configure file path.
:::
## RPM {#rpm}
**NOTE:** Only CentOS 7 is supported currently, for more information, please refer to [here](./deploy.md).
### Install
```shell
# 1. install RPM package
sudo yum install -y https://github.com/apache/apisix-dashboard/releases/download/v2.9.0/apisix-dashboard-2.9.0-0.el7.x86_64.rpm
```
### Launch
```shell
# run dashboard in the shell
sudo manager-api -p /usr/local/apisix/dashboard/
# or run dashboard as a service
systemctl apisix-dashboard start
```
Without changing the configuration, visit `http://127.0.0.1:9000` to use the dashboard with GUI, where the default username and password are `admin`.
## Source {#source}
The Dashboard project contains both `manager-api` and `web`, but `web` is _optional_.
The `manager-api` and `web` will be included in this build guide product.
### Prerequisites {#source-prerequisites}
Before using source codes to build, make sure that the following dependencies are installed in your environment.
For `manager-api`:
1. [Golang](https://golang.org/dl/) 1.13+
> Tip: For users in mainland China, you can use the following command to speed up the module downloads.
```sh
$ go env -w GOPROXY=https://goproxy.cn,direct
```
For `web`:
1. [Node.js](https://nodejs.org/en/download/) current LTS (14.x+)
2. [Yarn](https://yarnpkg.com/getting-started/install)
### Download {#source-download}
```shell
git clone -b release/2.9.0 https://github.com/apache/apisix-dashboard.git && cd apisix-dashboard
```
### Build {#source-build}
```shell
cd apisix-dashboard
make build
```
When the build is complete, the results are stored in the root `output` directory.
Note: `make build` will build `manager-api` and `web`, use the `make help` command to see more commands.
### Launch {#source-launch}
1. After the build is complete and before you start, make sure the following dependencies are installed and running in your environment.
- [etcd](https://etcd.io/docs/v3.4.0/dl-build/) 3.4.0+
2. Check and modify the configuration information in `output/conf/conf.yaml` according to your deployment environment.
3. Launch the Dashboard
```shell
cd ./output
./manager-api
```
4. Without changing the configuration, visit `http://127.0.0.1:9000` to use the dashboard with GUI, where the default username and password are `admin`.
### Service {#source-service}
You will need to handle your own service management when deploying using the source code compilation method. We provide a service file template for operating systems that use the Systemd service manager.
1. Install
```shell
mkdir -p /usr/local/apisix-dashboard
cp -rf ./output/* /usr/local/apisix-dashboard
```
2. Create service unit
Copy the following or use this [**file**](https://github.com/apache/apisix-dashboard/tree/master/service/apisix-dashboard.service) directly, you need to copy it to the `/usr/lib/systemd/system` directory and execute the `systemctl daemon-reload` command.
```shell
# copy service unit
cp ./api/service/apisix-dashboard.service /usr/lib/systemd/system/apisix-dashboard.service
systemctl daemon-reload
# or: If you need to modify the service unit, you can use the following command
echo "[Unit]
Description=apisix-dashboard
Conflicts=apisix-dashboard.service
After=network-online.target
[Service]
WorkingDirectory=/usr/local/apisix-dashboard
ExecStart=/usr/local/apisix-dashboard/manager-api -c /usr/local/apisix-dashboard/conf/conf.yaml" > /usr/lib/systemd/system/apisix-dashboard.service
```
3. Manage service
You can use the following command to manage the service.
```shell
# start apisix-dashboard
systemctl start apisix-dashboard
# stop apisix-dashboard
systemctl stop apisix-dashboard
# check apisix-dashboard status
systemctl status apisix-dashboard
```