2014-09-03 20:39:56 +00:00
|
|
|
/*
|
2015-05-01 16:19:44 +00:00
|
|
|
Copyright 2014 The Kubernetes Authors All rights reserved.
|
2014-09-03 20:39:56 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2015-04-30 01:04:58 +00:00
|
|
|
package lifecycle
|
2014-09-03 20:39:56 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net"
|
2014-09-24 21:27:10 +00:00
|
|
|
"strconv"
|
2014-09-03 20:39:56 +00:00
|
|
|
|
2015-08-05 22:05:17 +00:00
|
|
|
"github.com/golang/glog"
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/api"
|
|
|
|
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
2015-10-09 17:24:31 +00:00
|
|
|
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/util"
|
2014-09-03 20:39:56 +00:00
|
|
|
)
|
|
|
|
|
2015-04-30 01:04:58 +00:00
|
|
|
type HandlerRunner struct {
|
2015-10-09 17:24:31 +00:00
|
|
|
httpGetter kubetypes.HttpGetter
|
2015-05-11 22:32:51 +00:00
|
|
|
commandRunner kubecontainer.ContainerCommandRunner
|
2015-05-01 00:01:29 +00:00
|
|
|
containerManager podStatusProvider
|
|
|
|
}
|
|
|
|
|
|
|
|
type podStatusProvider interface {
|
|
|
|
GetPodStatus(pod *api.Pod) (*api.PodStatus, error)
|
2014-09-03 20:39:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-09 17:24:31 +00:00
|
|
|
func NewHandlerRunner(httpGetter kubetypes.HttpGetter, commandRunner kubecontainer.ContainerCommandRunner, containerManager podStatusProvider) kubecontainer.HandlerRunner {
|
2015-04-30 01:04:58 +00:00
|
|
|
return &HandlerRunner{
|
2015-04-20 23:58:10 +00:00
|
|
|
httpGetter: httpGetter,
|
|
|
|
commandRunner: commandRunner,
|
|
|
|
containerManager: containerManager,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-07 17:58:05 +00:00
|
|
|
func (hr *HandlerRunner) Run(containerID kubecontainer.ContainerID, pod *api.Pod, container *api.Container, handler *api.Handler) error {
|
2015-04-20 23:58:10 +00:00
|
|
|
switch {
|
|
|
|
case handler.Exec != nil:
|
|
|
|
_, err := hr.commandRunner.RunInContainer(containerID, handler.Exec.Command)
|
|
|
|
return err
|
|
|
|
case handler.HTTPGet != nil:
|
|
|
|
return hr.runHTTPHandler(pod, container, handler)
|
|
|
|
default:
|
|
|
|
err := fmt.Errorf("Invalid handler: %v", handler)
|
|
|
|
glog.Errorf("Cannot run handler: %v", err)
|
|
|
|
return err
|
|
|
|
}
|
2014-09-03 20:39:56 +00:00
|
|
|
}
|
|
|
|
|
2015-04-20 23:58:10 +00:00
|
|
|
// resolvePort attempts to turn a IntOrString port reference into a concrete port number.
|
2014-09-03 20:39:56 +00:00
|
|
|
// If portReference has an int value, it is treated as a literal, and simply returns that value.
|
|
|
|
// If portReference is a string, an attempt is first made to parse it as an integer. If that fails,
|
|
|
|
// an attempt is made to find a port with the same name in the container spec.
|
|
|
|
// If a port with the same name is found, it's ContainerPort value is returned. If no matching
|
|
|
|
// port is found, an error is returned.
|
2015-04-20 23:58:10 +00:00
|
|
|
func resolvePort(portReference util.IntOrString, container *api.Container) (int, error) {
|
2014-09-03 20:39:56 +00:00
|
|
|
if portReference.Kind == util.IntstrInt {
|
|
|
|
return portReference.IntVal, nil
|
|
|
|
} else {
|
|
|
|
portName := portReference.StrVal
|
|
|
|
port, err := strconv.Atoi(portName)
|
|
|
|
if err == nil {
|
|
|
|
return port, nil
|
|
|
|
}
|
|
|
|
for _, portSpec := range container.Ports {
|
|
|
|
if portSpec.Name == portName {
|
|
|
|
return portSpec.ContainerPort, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
return -1, fmt.Errorf("couldn't find port: %v in %v", portReference, container)
|
|
|
|
}
|
|
|
|
|
2015-04-30 01:04:58 +00:00
|
|
|
func (hr *HandlerRunner) runHTTPHandler(pod *api.Pod, container *api.Container, handler *api.Handler) error {
|
2014-09-03 20:39:56 +00:00
|
|
|
host := handler.HTTPGet.Host
|
|
|
|
if len(host) == 0 {
|
2015-04-20 23:58:10 +00:00
|
|
|
status, err := hr.containerManager.GetPodStatus(pod)
|
2014-09-03 20:39:56 +00:00
|
|
|
if err != nil {
|
2015-02-16 16:40:07 +00:00
|
|
|
glog.Errorf("Unable to get pod info, event handlers may be invalid.")
|
2014-09-03 20:39:56 +00:00
|
|
|
return err
|
|
|
|
}
|
2015-03-18 16:44:50 +00:00
|
|
|
if status.PodIP == "" {
|
2015-01-14 02:11:24 +00:00
|
|
|
return fmt.Errorf("failed to find networking container: %v", status)
|
2014-09-03 20:39:56 +00:00
|
|
|
}
|
2015-03-18 16:44:50 +00:00
|
|
|
host = status.PodIP
|
2014-09-03 20:39:56 +00:00
|
|
|
}
|
|
|
|
var port int
|
|
|
|
if handler.HTTPGet.Port.Kind == util.IntstrString && len(handler.HTTPGet.Port.StrVal) == 0 {
|
|
|
|
port = 80
|
|
|
|
} else {
|
|
|
|
var err error
|
2015-04-20 23:58:10 +00:00
|
|
|
port, err = resolvePort(handler.HTTPGet.Port, container)
|
2014-09-03 20:39:56 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
url := fmt.Sprintf("http://%s/%s", net.JoinHostPort(host, strconv.Itoa(port)), handler.HTTPGet.Path)
|
2015-04-20 23:58:10 +00:00
|
|
|
_, err := hr.httpGetter.Get(url)
|
2014-09-03 20:39:56 +00:00
|
|
|
return err
|
|
|
|
}
|