blob: de22508c8a8288d5bec433680613321e57156e67 [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 (
"encoding/json"
"fmt"
"os"
"os/signal"
"strings"
"syscall"
"time"
"github.com/spf13/cobra"
"github.com/apache/apisix-ingress-controller/pkg/config"
controller "github.com/apache/apisix-ingress-controller/pkg/ingress"
"github.com/apache/apisix-ingress-controller/pkg/log"
"github.com/apache/apisix-ingress-controller/pkg/version"
)
func dief(template string, args ...interface{}) {
if !strings.HasSuffix(template, "\n") {
template += "\n"
}
fmt.Fprintf(os.Stderr, template, args...)
os.Exit(1)
}
func waitForSignal(stopCh chan struct{}) {
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
sig := <-sigCh
log.Infof("signal %d (%s) received", sig, sig.String())
close(stopCh)
}
// NewIngressCommand creates the ingress sub command for apisix-ingress-controller.
func NewIngressCommand() *cobra.Command {
var configPath string
cfg := config.NewDefaultConfig()
cmd := &cobra.Command{
Use: "ingress [flags]",
Long: `launch the ingress controller
You can run apisix-ingress-controller from configuration file or command line options,
if you run it from configuration file, other command line options will be ignored.
Run from configuration file:
apisix-ingress-controller ingress --config-path /path/to/config.json
Both json and yaml are supported as the configuration file format.
Run from command line options:
apisix-ingress-controller ingress --apisix-base-url http://apisix-service:9180/apisix/admin --kubeconfig /path/to/kubeconfig
For Kubernetes cluster version older than v1.19.0, you should always set the --ingress-version option to networking/v1beta1:
apisix-ingress-controller ingress \
--apisix-base-url http://apisix-service:9180/apisix/admin \
--kubeconfig /path/to/kubeconfig \
--ingress-version networking/v1beta1
If your Kubernetes cluster version is prior to v1.14+, only ingress.extensions/v1beta1 can be used.
apisix-ingress-controller ingress \
--apisix-base-url http://apisix-service:9180/apisix/admin \
--kubeconfig /path/to/kubeconfig \
--ingress-version extensions/v1beta1
If you run apisix-ingress-controller outside the Kubernetes cluster, --kubeconfig option (or kubeconfig item in configuration file) should be specified explicitly,
or if you run it inside cluster, leave it alone and in-cluster configuration will be discovered and used.
Before you run apisix-ingress-controller, be sure all related resources, like CRDs (ApisixRoute, ApisixUpstream and etc),
the apisix cluster and others are created`,
Run: func(cmd *cobra.Command, args []string) {
if configPath != "" {
c, err := config.NewConfigFromFile(configPath)
if err != nil {
dief("failed to initialize configuration: %s", err)
}
cfg = c
}
if err := cfg.Validate(); err != nil {
dief("bad configuration: %s", err)
}
logger, err := log.NewLogger(
log.WithLogLevel(cfg.LogLevel),
log.WithOutputFile(cfg.LogOutput),
)
if err != nil {
dief("failed to initialize logging: %s", err)
}
log.DefaultLogger = logger
log.Info("apisix ingress controller started")
log.Info("version:\n", version.Long())
data, err := json.MarshalIndent(cfg, "", "\t")
if err != nil {
dief("failed to show configuration: %s", string(data))
}
log.Info("use configuration\n", string(data))
stop := make(chan struct{})
ingress, err := controller.NewController(cfg)
if err != nil {
dief("failed to create ingress controller: %s", err)
}
go func() {
if err := ingress.Run(stop); err != nil {
dief("failed to run ingress controller: %s", err)
}
}()
waitForSignal(stop)
log.Info("apisix ingress controller exited")
},
}
cmd.PersistentFlags().StringVar(&configPath, "config-path", "", "configuration file path for apisix-ingress-controller")
cmd.PersistentFlags().StringVar(&cfg.LogLevel, "log-level", "info", "error log level")
cmd.PersistentFlags().StringVar(&cfg.LogOutput, "log-output", "stderr", "error log output file")
cmd.PersistentFlags().StringVar(&cfg.HTTPListen, "http-listen", ":8080", "the HTTP Server listen address")
cmd.PersistentFlags().BoolVar(&cfg.EnableProfiling, "enable-profiling", true, "enable profiling via web interface host:port/debug/pprof")
cmd.PersistentFlags().StringVar(&cfg.Kubernetes.Kubeconfig, "kubeconfig", "", "Kubernetes configuration file (by default in-cluster configuration will be used)")
cmd.PersistentFlags().DurationVar(&cfg.Kubernetes.ResyncInterval.Duration, "resync-interval", time.Minute, "the controller resync (with Kubernetes) interval, the minimum resync interval is 30s")
cmd.PersistentFlags().StringSliceVar(&cfg.Kubernetes.AppNamespaces, "app-namespace", []string{config.NamespaceAll}, "namespaces that controller will watch for resources")
cmd.PersistentFlags().StringVar(&cfg.Kubernetes.IngressClass, "ingress-class", config.IngressClass, "the class of an Ingress object is set using the field IngressClassName in Kubernetes clusters version v1.18.0 or higher or the annotation \"kubernetes.io/ingress.class\" (deprecated)")
cmd.PersistentFlags().StringVar(&cfg.Kubernetes.ElectionID, "election-id", config.IngressAPISIXLeader, "election id used for campaign the controller leader")
cmd.PersistentFlags().StringVar(&cfg.Kubernetes.IngressVersion, "ingress-version", config.IngressNetworkingV1, "the supported ingress api group version, can be \"networking/v1beta1\", \"networking/v1\" (for Kubernetes version v1.19.0 or higher) and \"extensions/v1beta1\"")
cmd.PersistentFlags().StringVar(&cfg.Kubernetes.ApisixRouteVersion, "apisix-route-version", config.ApisixRouteV2alpha1, "the supported apisixroute api group version, can be \"apisix.apache.org/v1\" or \"apisix.apache.org/v2alpha1\"")
cmd.PersistentFlags().BoolVar(&cfg.Kubernetes.WatchEndpointSlices, "watch-endpointslices", false, "whether to watch endpointslices rather than endpoints")
cmd.PersistentFlags().StringVar(&cfg.APISIX.BaseURL, "apisix-base-url", "", "the base URL for APISIX admin api / manager api (deprecated, using --default-apisix-cluster-base-url instead)")
cmd.PersistentFlags().StringVar(&cfg.APISIX.AdminKey, "apisix-admin-key", "", "admin key used for the authorization of APISIX admin api / manager api (deprecated, using --default-apisix-cluster-admin-key instead)")
cmd.PersistentFlags().StringVar(&cfg.APISIX.DefaultClusterBaseURL, "default-apisix-cluster-base-url", "", "the base URL of admin api / manager api for the default APISIX cluster")
cmd.PersistentFlags().StringVar(&cfg.APISIX.DefaultClusterAdminKey, "default-apisix-cluster-admin-key", "", "admin key used for the authorization of admin api / manager api for the default APISIX cluster")
cmd.PersistentFlags().StringVar(&cfg.APISIX.DefaultClusterName, "default-apisix-cluster-name", "default", "name of the default apisix cluster")
return cmd
}