diff --git a/cmd/gateway/option/option.go b/cmd/gateway/option/option.go index dab4100f9..34038f725 100644 --- a/cmd/gateway/option/option.go +++ b/cmd/gateway/option/option.go @@ -21,7 +21,6 @@ package option import ( "fmt" "github.com/Sirupsen/logrus" - "github.com/goodrain/rainbond/gateway/controller/openresty/model" "github.com/spf13/pflag" ) @@ -36,10 +35,17 @@ func NewGWServer() *GWServer { //Config contains all configuration type Config struct { - Nginx model.Nginx - Http model.Http K8SConfPath string - Namespace string + Namespace string + ListenPorts ListenPorts +} + +// ListenPorts describe the ports required to run the gateway controller +type ListenPorts struct { + HTTP int + HTTPS int + Status int + AuxiliaryPort int } // AddFlags adds flags @@ -48,6 +54,7 @@ func (g *GWServer) AddFlags(fs *pflag.FlagSet) { // TODO change kube-conf fs.StringVar(&g.K8SConfPath, "kube-conf", "/Users/abe/Documents/admin.kubeconfig", "absolute path to the kubeconfig file") fs.StringVar(&g.Namespace, "namespace", "gateway", "namespace") + fs.IntVar(&g.ListenPorts.AuxiliaryPort, "auxiliary-port", 10253, "port of auxiliary server") } // SetLog sets log diff --git a/cmd/gateway/server/server.go b/cmd/gateway/server/server.go index 8d440e68c..0009b8286 100644 --- a/cmd/gateway/server/server.go +++ b/cmd/gateway/server/server.go @@ -20,18 +20,38 @@ package server import ( "fmt" + "github.com/Sirupsen/logrus" "github.com/goodrain/rainbond/cmd/gateway/option" "github.com/goodrain/rainbond/gateway/controller" + "os" + "os/signal" + "syscall" ) //Run start run func Run(s *option.GWServer) error { - gwc := controller.NewGWController() + errCh := make(chan error) + + gwc := controller.NewGWController( + &s.Config, + errCh) if gwc == nil { return fmt.Errorf("fail to new GWController") } - gwc.Start() + if err := gwc.Start(); err != nil { + return err + } + defer gwc.Stop() + term := make(chan os.Signal) + signal.Notify(term, os.Interrupt, syscall.SIGTERM) + select { + case <-term: + logrus.Warn("Received SIGTERM, exiting gracefully...") + case err := <-errCh: + logrus.Errorf("Received a error %s, exiting gracefully...", err.Error()) + } + logrus.Info("See you next time!") return nil } diff --git a/gateway/controller/controller.go b/gateway/controller/controller.go index 2e673c70d..9d928515e 100644 --- a/gateway/controller/controller.go +++ b/gateway/controller/controller.go @@ -1,6 +1,7 @@ package controller import ( + "fmt" "github.com/Sirupsen/logrus" "github.com/eapache/channels" "github.com/golang/glog" @@ -8,19 +9,28 @@ import ( "github.com/goodrain/rainbond/gateway/controller/openresty" "github.com/goodrain/rainbond/gateway/store" "github.com/goodrain/rainbond/gateway/v1" + "k8s.io/client-go/util/flowcontrol" "k8s.io/ingress-nginx/task" + "sync" "time" ) const ( - TRY_TIMES = 2 + TryTimes = 2 ) type GWController struct { - GWS GWServicer - store store.Storer // TODO 为什么不能是*store.Storer - syncQueue *task.Queue - isShuttingDown bool + GWS GWServicer + store store.Storer + + syncQueue *task.Queue + syncRateLimiter flowcontrol.RateLimiter + isShuttingDown bool + + // stopLock is used to enforce that only a single call to Stop send at + // a given time. We allow stopping through an HTTP endpoint and + // allowing concurrent stoppers leads to stack traces. + stopLock *sync.Mutex optionConfig option.Config RunningConfig *v1.Config @@ -28,7 +38,7 @@ type GWController struct { stopCh chan struct{} updateCh *channels.RingChannel - errCh chan error // errCh is used to detect errors with the NGINX processes + errCh chan error // TODO: never used } func (gwc *GWController) syncGateway(key interface{}) error { @@ -55,44 +65,43 @@ func (gwc *GWController) syncGateway(key interface{}) error { gwc.RunningConfig = currentConfig err := gwc.GWS.PersistConfig(gwc.RunningConfig) - // TODO: check if the nginx is ready. - // refresh http pools dynamically - gwc.refreshPools(httpPools) - gwc.RunningHttpPools = httpPools if err != nil { logrus.Errorf("Fail to persist Nginx config: %v\n", err) + } else { + // refresh http pools dynamically + gwc.refreshPools(httpPools) + gwc.RunningHttpPools = httpPools } return nil } -func (gwc *GWController) Start() { +func (gwc *GWController) Start() error { gwc.store.Run(gwc.stopCh) - gws := &openresty.OpenrestyService{} - err := gws.Start() + err := gwc.GWS.Start() if err != nil { - logrus.Fatalf("Can not start gateway plugin: %v", err) - return + return fmt.Errorf("Can not start gateway plugin: %v", err) } go gwc.syncQueue.Run(1*time.Second, gwc.stopCh) // force initial sync gwc.syncQueue.EnqueueTask(task.GetDummyObject("initial-sync")) + go gwc.handleEvent() + + return nil +} + +func (gwc *GWController) handleEvent() { for { select { - case event := <-gwc.updateCh.Out(): // 将ringChannel的output通道接收到event放到task.Queue中 + case event := <-gwc.updateCh.Out(): if gwc.isShuttingDown { break } if evt, ok := event.(store.Event); ok { logrus.Infof("Event %v received - object %v", evt.Type, evt.Obj) - if evt.Type == store.ConfigurationEvent { - // TODO: is this necessary? Consider removing this special case - gwc.syncQueue.EnqueueTask(task.GetDummyObject("configmap-change")) - continue - } gwc.syncQueue.EnqueueSkippableTask(evt.Obj) } else { glog.Warningf("Unexpected event type received %T", event) @@ -103,16 +112,35 @@ func (gwc *GWController) Start() { } } +func (gwc *GWController) Stop() error { + gwc.isShuttingDown = true + + gwc.stopLock.Lock() + defer gwc.stopLock.Unlock() + + if gwc.syncQueue.IsShuttingDown() { + return fmt.Errorf("shutdown already in progress") + } + + logrus.Infof("Shutting down controller queues") + close(gwc.stopCh) // stop the loop in *GWController#Start() + go gwc.syncQueue.Shutdown() + + return gwc.GWS.Stop() +} + // refreshPools refresh pools dynamically. func (gwc *GWController) refreshPools(pools []*v1.Pool) { + gwc.GWS.WaitPluginReady() + delPools, updPools := gwc.getDelUpdPools(pools) - for i := 0; i < TRY_TIMES; i++ { + for i := 0; i < TryTimes; i++ { err := gwc.GWS.UpdatePools(updPools) if err == nil { break } } - for i := 0; i < TRY_TIMES; i++ { + for i := 0; i < TryTimes; i++ { err := gwc.GWS.DeletePools(delPools) if err == nil { break @@ -142,23 +170,29 @@ func (gwc *GWController) getDelUpdPools(updPools []*v1.Pool) ([]*v1.Pool, []*v1. return delPools, updPools } -func NewGWController() *GWController { +func NewGWController(config *option.Config, errCh chan error) *GWController { logrus.Debug("NewGWController...") gwc := &GWController{ updateCh: channels.NewRingChannel(1024), - errCh: make(chan error), + errCh: errCh, + stopLock: &sync.Mutex{}, + stopCh: make(chan struct{}), } - gws := &openresty.OpenrestyService{} + gws := &openresty.OpenrestyService{ + AuxiliaryPort: config.ListenPorts.AuxiliaryPort, + IsShuttingDown: &gwc.isShuttingDown, + } gwc.GWS = gws - clientSet, err := NewClientSet("/Users/abe/Documents/admin.kubeconfig") + clientSet, err := NewClientSet(config.K8SConfPath) if err != nil { - // TODO + logrus.Error("can't create kubernetes's client.") } - gwc.store = store.New(clientSet, - "gateway", + gwc.store = store.New( + clientSet, + config.Namespace, gwc.updateCh) gwc.syncQueue = task.NewTaskQueue(gwc.syncGateway) diff --git a/gateway/controller/openresty/service.go b/gateway/controller/openresty/service.go index 7ae5e2788..84f31c5a9 100644 --- a/gateway/controller/openresty/service.go +++ b/gateway/controller/openresty/service.go @@ -9,11 +9,23 @@ import ( "github.com/goodrain/rainbond/gateway/controller/openresty/template" "github.com/goodrain/rainbond/gateway/v1" "io/ioutil" + "k8s.io/ingress-nginx/ingress/controller/process" "net/http" + "os" "strings" + "sync" + "time" ) -type OpenrestyService struct{} +type OpenrestyService struct{ + AuxiliaryPort int + IsShuttingDown *bool + + // stopLock is used to enforce that only a single call to Stop send at + // a given time. We allow stopping through an HTTP endpoint and + // allowing concurrent stoppers leads to stack traces. + stopLock *sync.Mutex +} type Upstream struct { Name string @@ -26,10 +38,35 @@ type Server struct { } func (osvc *OpenrestyService) Start() error { - //o, err := nginxExecCommand().CombinedOutput() - //if err != nil { - // return fmt.Errorf("%v\n%v", err, string(o)) - //} + o, err := nginxExecCommand().CombinedOutput() + if err != nil { + return fmt.Errorf("%v\n%v", err, string(o)) + } + return nil +} + +// Stop gracefully stops the NGINX master process. +func (osvc *OpenrestyService) Stop() error { + // send stop signal to NGINX + logrus.Info("Stopping NGINX process") + cmd := nginxExecCommand("-s", "quit") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err := cmd.Run() + if err != nil { + return err + } + + // wait for the NGINX process to terminate + timer := time.NewTicker(time.Second * 1) + for range timer.C { + if !process.IsNginxRunning() { + logrus.Info("NGINX process has stopped") + timer.Stop() + break + } + } + return nil } @@ -100,9 +137,9 @@ func (osvc *OpenrestyService) PersistConfig(conf *v1.Config) error { logrus.Debug("Nginx configuration is ok.") // reload nginx - //if out, err := nginxExecCommand("-s", "reload").CombinedOutput(); err != nil { - // return fmt.Errorf("%v\n%v", err, string(out)) - //} + if out, err := nginxExecCommand("-s", "reload").CombinedOutput(); err != nil { + return fmt.Errorf("%v\n%v", err, string(out)) + } logrus.Debug("Nginx reloads successfully.") return nil @@ -171,7 +208,9 @@ func getNgxServer(conf *v1.Config) (l7srv []*model.Server, l4srv []*model.Server // UpdatePools updates http upstreams dynamically. func (osvc *OpenrestyService) UpdatePools(pools []*v1.Pool) error { - logrus.Debug("update http upstreams dynamically.") + if len(pools) == 0 { + return nil + } var upstreams []*Upstream for _, pool := range pools { upstream := &Upstream{} @@ -185,16 +224,16 @@ func (osvc *OpenrestyService) UpdatePools(pools []*v1.Pool) error { } upstreams = append(upstreams, upstream) } - return updateUpstreams(upstreams) + return osvc.updateUpstreams(upstreams) } // updateUpstreams updates the upstreams in ngx.shared.dict by post -func updateUpstreams(upstream []*Upstream) error { - url := "http://localhost:33333/update-upstreams" // TODO - json, _ := json.Marshal(upstream) - logrus.Debugf("request contest of update-upstreams is %v", string(json)) +func (osvc *OpenrestyService) updateUpstreams(upstream []*Upstream) error { + url := fmt.Sprintf("http://127.0.0.1:%v/update-upstreams", osvc.AuxiliaryPort) + data, _ := json.Marshal(upstream) + logrus.Debugf("request contest of update-upstreams is %v", string(data)) - resp, err := http.Post(url, "application/json", bytes.NewBuffer(json)) + resp, err := http.Post(url, "application/json", bytes.NewBuffer(data)) if err != nil { logrus.Errorf("fail to update upstreams: %v", err) return err @@ -213,18 +252,21 @@ func updateUpstreams(upstream []*Upstream) error { } func (osvc *OpenrestyService) DeletePools(pools []*v1.Pool) error { + if len(pools) == 0 { + return nil + } var data []string for _, pool := range pools { data = append(data, pool.Name) } - return deletePools(data) + return osvc.deletePools(data) } -func deletePools(data []string) error { - url := "http://localhost:33333/delete-upstreams" // TODO - json, _ := json.Marshal(data) - logrus.Errorf("request content of delete-upstreams is %v", string(json)) +func (osvc *OpenrestyService) deletePools(names []string) error { + url := fmt.Sprintf("http://127.0.0.1:%v/delete-upstreams", osvc.AuxiliaryPort) + data, _ := json.Marshal(names) + logrus.Errorf("request content of delete-upstreams is %v", string(data)) - resp, err := http.Post(url, "application/json", bytes.NewBuffer(json)) + resp, err := http.Post(url, "application/json", bytes.NewBuffer(data)) if err != nil { logrus.Errorf("fail to delete upstreams: %v", err) return err @@ -233,4 +275,17 @@ func deletePools(data []string) error { logrus.Debugf("the status of dynamically deleting upstreams is %v.", resp.Status) return nil -} \ No newline at end of file +} + +// WaitPluginReady waits for nginx to be ready. +func (osvc *OpenrestyService) WaitPluginReady() { + url := fmt.Sprintf("http://127.0.0.1:%v/healthz", osvc.AuxiliaryPort) + for { + resp, err := http.Get(url) + if err == nil && resp.StatusCode == 200 { + logrus.Info("Nginx is ready") + break + } + time.Sleep(200 * time.Microsecond) + } +} diff --git a/gateway/controller/openresty/template/template.go b/gateway/controller/openresty/template/template.go index 0ff09b746..174f6dd78 100644 --- a/gateway/controller/openresty/template/template.go +++ b/gateway/controller/openresty/template/template.go @@ -50,7 +50,7 @@ func NewTemplate(fileName string) (*Template, error) { } // TODO change the template name - tmpl, err := text_template.New("").Funcs(funcMap).Parse(string(tmplFile)) + tmpl, err := text_template.New("gateway").Funcs(funcMap).Parse(string(tmplFile)) if err != nil { return nil, err } diff --git a/gateway/controller/service.go b/gateway/controller/service.go index 6f55498e5..98570f880 100644 --- a/gateway/controller/service.go +++ b/gateway/controller/service.go @@ -9,4 +9,6 @@ type GWServicer interface { PersistConfig(conf *v1.Config) error UpdatePools(pools []*v1.Pool) error DeletePools(pools []*v1.Pool) error + WaitPluginReady() + Stop() error } diff --git a/gateway/rootfs/export/servers/nginx/tmpl/http.tmpl b/gateway/rootfs/export/servers/nginx/tmpl/http.tmpl index 36ff9c6c2..a0085228c 100644 --- a/gateway/rootfs/export/servers/nginx/tmpl/http.tmpl +++ b/gateway/rootfs/export/servers/nginx/tmpl/http.tmpl @@ -50,8 +50,31 @@ http { lua_shared_dict upstreams_dict 16m; + upstream def_upstream { + server localhost:7777 max_fails=2 fail_timeout=30s; + server localhost:8888 max_fails=2 fail_timeout=30s; + } + server { - listen 33333; + listen 10254; + + location /healthz { + return 200 "ok"; + } + + location /list-upstreams { + content_by_lua_block { + local balancer = require "ngx.balancer" + local cjson = require("cjson") + local keys = ngx.shared.upstreams_dict:get_keys() + for _, name in pairs(keys) do + local servers = ngx.shared.upstreams_dict:get(name) + ngx.print(name..": ") + ngx.print(cjson.encode(servers)) + ngx.print("\n") + end + } + } location /update-upstreams { content_by_lua_block { @@ -76,16 +99,14 @@ http { } } - location /list-upstreams { + location /delete-upstreams { content_by_lua_block { - local balancer = require "ngx.balancer" local cjson = require("cjson") - local keys = ngx.shared.upstreams_dict:get_keys() - for _, name in pairs(keys) do - local servers = ngx.shared.upstreams_dict:get(name) - ngx.print(name..": ") - ngx.print(cjson.encode(servers)) - ngx.print("\n") + ngx.req.read_body() + local data = ngx.req.get_body_data() + local tbl = cjson.decode(data) + for _, name in pairs(tbl) do + ngx.shared.upstreams_dict:delete(name) end } } diff --git a/gateway/store/store.go b/gateway/store/store.go index c124d3fc7..605190bf2 100644 --- a/gateway/store/store.go +++ b/gateway/store/store.go @@ -300,7 +300,6 @@ func (s *rbdStore) extractAnnotations(ing *extensions.Ingress) { } } -// TODO test func (s *rbdStore) ListPool() ([]*v1.Pool, []*v1.Pool) { var httpPools []*v1.Pool var tcpPools []*v1.Pool @@ -308,12 +307,12 @@ func (s *rbdStore) ListPool() ([]*v1.Pool, []*v1.Pool) { endpoint := item.(*corev1.Endpoints) pool := &v1.Pool{ - Nodes: []v1.Node{}, + Nodes: []*v1.Node{}, } pool.Name = endpoint.ObjectMeta.Name - for _, ss := range endpoint.Subsets { // TODO 这个SubSets为什么是slice? + for _, ss := range endpoint.Subsets { for _, address := range ss.Addresses { - pool.Nodes = append(pool.Nodes, v1.Node{ // TODO 需不需要用指针? + pool.Nodes = append(pool.Nodes, &v1.Node{ Host: address.IP, Port: ss.Ports[0].Port, }) diff --git a/gateway/v1/node.go b/gateway/v1/node.go index c53ece91c..e056b6e94 100644 --- a/gateway/v1/node.go +++ b/gateway/v1/node.go @@ -23,14 +23,14 @@ type Node struct { Meta Host string `json:"host"` Port int32 `json:"port"` - Protocol string `json:"protocol"` //TODO: 应该新建几个类型??? + Protocol string `json:"protocol"` State string `json:"state"` //Active Draining Disabled - PoolName string `json:"pool_name"` //Belong to the pool TODO: PoolName中能有空格吗??? + PoolName string `json:"pool_name"` //Belong to the pool Ready bool `json:"ready"` //Whether ready Weight int `json:"weight"` } -func (n *Node) Equals(c *Node) bool { // TODO 这个Equals方法可以抽象出去吗??? +func (n *Node) Equals(c *Node) bool { // if n == c { return true } diff --git a/gateway/v1/pool.go b/gateway/v1/pool.go index 673357eb4..89557e493 100644 --- a/gateway/v1/pool.go +++ b/gateway/v1/pool.go @@ -32,7 +32,7 @@ type Pool struct { NodeNumber int `json:"node_number"` LoadBalancingType LoadBalancingType `json:"load_balancing_type"` Monitors []Monitor `json:"monitors"` - Nodes []Node + Nodes []*Node } func (p *Pool) Equals(c *Pool) bool { @@ -86,7 +86,7 @@ func (p *Pool) Equals(c *Pool) bool { for _, a := range p.Nodes { flag := false for _, b := range c.Nodes { - if a.Equals(&b) { + if a.Equals(b) { flag = true } } diff --git a/gateway/v1/pool_test.go b/gateway/v1/pool_test.go index eb647aa41..8065e9a65 100644 --- a/gateway/v1/pool_test.go +++ b/gateway/v1/pool_test.go @@ -26,9 +26,9 @@ func TestPool_Equals(t *testing.T) { node2 := newFakeNode() node2.Name = "node-b" p := NewFakePoolWithoutNodes() - p.Nodes = []Node{ - *node1, - *node2, + p.Nodes = []*Node{ + node1, + node2, } node3 := newFakeNode() @@ -36,9 +36,9 @@ func TestPool_Equals(t *testing.T) { node4 := newFakeNode() node4.Name = "node-b" c := NewFakePoolWithoutNodes() - c.Nodes = []Node { - *node3, - *node4, + c.Nodes = []*Node { + node3, + node4, } if !p.Equals(c) { diff --git a/gateway/v1/virtual_service.go b/gateway/v1/virtual_service.go index 1a4e6645e..573a06865 100644 --- a/gateway/v1/virtual_service.go +++ b/gateway/v1/virtual_service.go @@ -77,7 +77,7 @@ func (v *VirtualService) Equals(c *VirtualService) bool { return false } - // TODO + // TODO: this snippet needs improvement if len(v.Listening) != len(c.Listening) { return false } @@ -101,7 +101,7 @@ func (v *VirtualService) Equals(c *VirtualService) bool { return false } - // TODO + // TODO: this snippet needs improvement if len(v.RuleNames) != len(c.RuleNames) { return false } @@ -163,5 +163,9 @@ func (v *VirtualService) Equals(c *VirtualService) bool { } } + if !v.SSLCert.Equals(c.SSLCert) { + return false + } + return true } diff --git a/gateway/v1/virtual_service_test.go b/gateway/v1/virtual_service_test.go index 6246d9cae..c29dcaf95 100644 --- a/gateway/v1/virtual_service_test.go +++ b/gateway/v1/virtual_service_test.go @@ -28,6 +28,7 @@ func TestVirtualService_Equals(t *testing.T) { vlocB.PoolName = "pool-bbb" v.Locations = append(v.Locations, vlocA) v.Locations = append(v.Locations, vlocB) + v.SSLCert = newFakeSSLCert() c := newFakeVirtualService() clocA:= newFakeLocation() @@ -36,6 +37,8 @@ func TestVirtualService_Equals(t *testing.T) { clocB.PoolName = "pool-bbb" c.Locations = append(c.Locations, clocA) c.Locations = append(c.Locations, clocB) + c.SSLCert = newFakeSSLCert() + if !v.Equals(c) { t.Errorf("v should equal c") @@ -55,7 +58,6 @@ func newFakeVirtualService() *VirtualService { RuleNames: []string{"a", "b", "c"}, SSLdecrypt: true, DefaultCertificateName: "default-certificate-name", - CertificateMapping: map[string]string{"a": "aaa", "b": "bbb", "c": "ccc"}, RequestLogEnable: true, RequestLogFileName: "/var/log/gateway/request.log", RequestLogFormat: "request-log-format", @@ -63,5 +65,6 @@ func newFakeVirtualService() *VirtualService { Timeout: 70, ServerName:"foo-server_name", PoolName: "foo-pool-name", + ForceSSLRedirect: true, } } diff --git a/vendor/k8s.io/ingress-nginx/ingress/controller/process/nginx.go b/vendor/k8s.io/ingress-nginx/ingress/controller/process/nginx.go new file mode 100644 index 000000000..a4777adae --- /dev/null +++ b/vendor/k8s.io/ingress-nginx/ingress/controller/process/nginx.go @@ -0,0 +1,95 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed 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 process + +import ( + "fmt" + "net" + "os" + "os/exec" + "syscall" + "time" + + "github.com/golang/glog" + ps "github.com/mitchellh/go-ps" + "github.com/ncabatoff/process-exporter/proc" +) + +// IsRespawnIfRequired checks if error type is exec.ExitError or not +func IsRespawnIfRequired(err error) bool { + exitError, ok := err.(*exec.ExitError) + if !ok { + return false + } + + waitStatus := exitError.Sys().(syscall.WaitStatus) + glog.Warningf(` +------------------------------------------------------------------------------- +NGINX master process died (%v): %v +------------------------------------------------------------------------------- +`, waitStatus.ExitStatus(), err) + return true +} + +// WaitUntilPortIsAvailable waits until there is no NGINX master or worker +// process/es listening in a particular port. +func WaitUntilPortIsAvailable(port int) { + // we wait until the workers are killed + for { + conn, err := net.DialTimeout("tcp", fmt.Sprintf("0.0.0.0:%v", port), 1*time.Second) + if err != nil { + break + } + conn.Close() + // kill nginx worker processes + fs, err := proc.NewFS("/proc") + if err != nil { + glog.Errorf("unexpected error reading /proc information: %v", err) + continue + } + + procs, _ := fs.FS.AllProcs() + for _, p := range procs { + pn, err := p.Comm() + if err != nil { + glog.Errorf("unexpected error obtaining process information: %v", err) + continue + } + + if pn == "nginx" { + osp, err := os.FindProcess(p.PID) + if err != nil { + glog.Errorf("unexpected error obtaining process information: %v", err) + continue + } + osp.Signal(syscall.SIGQUIT) + } + } + time.Sleep(100 * time.Millisecond) + } +} + +// IsNginxRunning returns true if a process with the name 'nginx' is found +func IsNginxRunning() bool { + processes, _ := ps.Processes() + for _, p := range processes { + if p.Executable() == "nginx" { + return true + } + } + return false +} diff --git a/vendor/k8s.io/ingress-nginx/vendor/github.com/mitchellh/go-ps/.gitignore b/vendor/k8s.io/ingress-nginx/vendor/github.com/mitchellh/go-ps/.gitignore new file mode 100644 index 000000000..a977916f6 --- /dev/null +++ b/vendor/k8s.io/ingress-nginx/vendor/github.com/mitchellh/go-ps/.gitignore @@ -0,0 +1 @@ +.vagrant/ diff --git a/vendor/k8s.io/ingress-nginx/vendor/github.com/mitchellh/go-ps/.travis.yml b/vendor/k8s.io/ingress-nginx/vendor/github.com/mitchellh/go-ps/.travis.yml new file mode 100644 index 000000000..8f794f71d --- /dev/null +++ b/vendor/k8s.io/ingress-nginx/vendor/github.com/mitchellh/go-ps/.travis.yml @@ -0,0 +1,4 @@ +language: go + +go: + - 1.2.1 diff --git a/vendor/k8s.io/ingress-nginx/vendor/github.com/mitchellh/go-ps/LICENSE.md b/vendor/k8s.io/ingress-nginx/vendor/github.com/mitchellh/go-ps/LICENSE.md new file mode 100644 index 000000000..229851590 --- /dev/null +++ b/vendor/k8s.io/ingress-nginx/vendor/github.com/mitchellh/go-ps/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/k8s.io/ingress-nginx/vendor/github.com/mitchellh/go-ps/README.md b/vendor/k8s.io/ingress-nginx/vendor/github.com/mitchellh/go-ps/README.md new file mode 100644 index 000000000..8e8baf9d2 --- /dev/null +++ b/vendor/k8s.io/ingress-nginx/vendor/github.com/mitchellh/go-ps/README.md @@ -0,0 +1,34 @@ +# Process List Library for Go + +go-ps is a library for Go that implements OS-specific APIs to list and +manipulate processes in a platform-safe way. The library can find and +list processes on Linux, Mac OS X, Solaris, and Windows. + +If you're new to Go, this library has a good amount of advanced Go educational +value as well. It uses some advanced features of Go: build tags, accessing +DLL methods for Windows, cgo for Darwin, etc. + +How it works: + + * **Darwin** uses the `sysctl` syscall to retrieve the process table. + * **Unix** uses the procfs at `/proc` to inspect the process tree. + * **Windows** uses the Windows API, and methods such as + `CreateToolhelp32Snapshot` to get a point-in-time snapshot of + the process table. + +## Installation + +Install using standard `go get`: + +``` +$ go get github.com/mitchellh/go-ps +... +``` + +## TODO + +Want to contribute? Here is a short TODO list of things that aren't +implemented for this library that would be nice: + + * FreeBSD support + * Plan9 support diff --git a/vendor/k8s.io/ingress-nginx/vendor/github.com/mitchellh/go-ps/Vagrantfile b/vendor/k8s.io/ingress-nginx/vendor/github.com/mitchellh/go-ps/Vagrantfile new file mode 100644 index 000000000..61662ab1e --- /dev/null +++ b/vendor/k8s.io/ingress-nginx/vendor/github.com/mitchellh/go-ps/Vagrantfile @@ -0,0 +1,43 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! +VAGRANTFILE_API_VERSION = "2" + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.box = "chef/ubuntu-12.04" + + config.vm.provision "shell", inline: $script + + ["vmware_fusion", "vmware_workstation"].each do |p| + config.vm.provider "p" do |v| + v.vmx["memsize"] = "1024" + v.vmx["numvcpus"] = "2" + v.vmx["cpuid.coresPerSocket"] = "1" + end + end +end + +$script = <