// TODO(floreks): This should be transactional to make sure that DS will not be deleted without pods // Deletes daemon set with given name in given namespace and related pods. // Also deletes services related to daemon set if deleteServices is true. func DeleteDaemonSet(client k8sClient.Interface, namespace, name string, deleteServices bool) error { log.Printf("Deleting %s daemon set from %s namespace", name, namespace) if deleteServices { if err := DeleteDaemonSetServices(client, namespace, name); err != nil { return err } } pods, err := getRawDaemonSetPods(client, namespace, name) if err != nil { return err } if err := client.Extensions().DaemonSets(namespace).Delete(name); err != nil { return err } for _, pod := range pods.Items { if err := client.Pods(namespace).Delete(pod.Name, &api.DeleteOptions{}); err != nil { return err } } log.Printf("Successfully deleted %s daemon set from %s namespace", name, namespace) return nil }
func StatusViewerFor(kind unversioned.GroupKind, c client.Interface) (StatusViewer, error) { switch kind { case extensions.Kind("Deployment"): return &DeploymentStatusViewer{c.Extensions()}, nil } return nil, fmt.Errorf("no status viewer has been implemented for %v", kind) }
// GetDeploymentDetail returns model object of deployment and error, if any. func GetDeploymentDetail(client client.Interface, namespace string, name string) (*DeploymentDetail, error) { log.Printf("Getting details of %s deployment in %s namespace", name, namespace) deployment, err := client.Extensions().Deployments(namespace).Get(name) if err != nil { return nil, err } selector, err := unversioned.LabelSelectorAsSelector(deployment.Spec.Selector) if err != nil { return nil, err } options := api.ListOptions{LabelSelector: selector} channels := &common.ResourceChannels{ ReplicaSetList: common.GetReplicaSetListChannelWithOptions(client.Extensions(), common.NewSameNamespaceQuery(namespace), options, 1), PodList: common.GetPodListChannelWithOptions(client, common.NewSameNamespaceQuery(namespace), options, 1), EventList: common.GetEventListChannelWithOptions(client, common.NewSameNamespaceQuery(namespace), options, 1), } rsList := <-channels.ReplicaSetList.List if err := <-channels.ReplicaSetList.Error; err != nil { return nil, err } podList := <-channels.PodList.List if err := <-channels.PodList.Error; err != nil { return nil, err } eventList := <-channels.EventList.List if err := <-channels.EventList.Error; err != nil { return nil, err } oldReplicaSets, _, err := deploymentutil.FindOldReplicaSets(deployment, rsList.Items, podList) if err != nil { return nil, err } newReplicaSet, err := deploymentutil.FindNewReplicaSet(deployment, rsList.Items) if err != nil { return nil, err } events, err := GetDeploymentEvents(eventList.Items, namespace, name) if err != nil { return nil, err } return getDeploymentDetail(deployment, oldReplicaSets, newReplicaSet, podList.Items, events, eventList.Items), nil }
func ScalerFor(kind string, c client.Interface) (Scaler, error) { switch kind { case "ReplicationController": return &ReplicationControllerScaler{c}, nil case "Job": return &JobScaler{c.Extensions()}, nil case "Deployment": return &DeploymentScaler{c.Extensions()}, nil } return nil, fmt.Errorf("no scaler has been implemented for %q", kind) }
func ScalerFor(kind unversioned.GroupKind, c client.Interface) (Scaler, error) { switch kind { case api.Kind("ReplicationController"): return &ReplicationControllerScaler{c}, nil case extensions.Kind("Job"): return &JobScaler{c.Extensions()}, nil case extensions.Kind("Deployment"): return &DeploymentScaler{c.Extensions()}, nil } return nil, fmt.Errorf("no scaler has been implemented for %q", kind) }
// GetDeploymentEvents returns model events for a deployment with the given name in the given // namespace func GetDeploymentOldReplicaSets(client client.Interface, dsQuery *dataselect.DataSelectQuery, namespace string, deploymentName string) (*replicasetlist.ReplicaSetList, error) { deployment, err := client.Extensions().Deployments(namespace).Get(deploymentName) if err != nil { return nil, err } selector, err := unversioned.LabelSelectorAsSelector(deployment.Spec.Selector) if err != nil { return nil, err } options := api.ListOptions{LabelSelector: selector} channels := &common.ResourceChannels{ ReplicaSetList: common.GetReplicaSetListChannelWithOptions(client.Extensions(), common.NewSameNamespaceQuery(namespace), options, 1), PodList: common.GetPodListChannelWithOptions(client, common.NewSameNamespaceQuery(namespace), options, 1), EventList: common.GetEventListChannelWithOptions(client, common.NewSameNamespaceQuery(namespace), options, 1), } rawRs := <-channels.ReplicaSetList.List if err := <-channels.ReplicaSetList.Error; err != nil { return nil, err } rawPods := <-channels.PodList.List if err := <-channels.PodList.Error; err != nil { return nil, err } rawEvents := <-channels.EventList.List if err := <-channels.EventList.Error; err != nil { return nil, err } rawRepSets := make([]*extensions.ReplicaSet, 0) for i := range rawRs.Items { rawRepSets = append(rawRepSets, &rawRs.Items[i]) } oldRs, _, err := deploymentutil.FindOldReplicaSets(deployment, rawRepSets, rawPods) if err != nil { return nil, err } oldReplicaSets := make([]extensions.ReplicaSet, len(oldRs)) for i, replicaSet := range oldRs { oldReplicaSets[i] = *replicaSet } oldReplicaSetList := replicasetlist.CreateReplicaSetList(oldReplicaSets, rawPods.Items, rawEvents.Items, dsQuery, nil) return oldReplicaSetList, nil }
func ScalerFor(kind unversioned.GroupKind, c client.Interface) (Scaler, error) { switch kind { case api.Kind("ReplicationController"): return &ReplicationControllerScaler{c}, nil case extensions.Kind("ReplicaSet"): return &ReplicaSetScaler{c.Extensions()}, nil case extensions.Kind("Job"): return &JobScaler{c.Extensions()}, nil // TODO(madhusudancs): Fix this when Scale group issues are resolved (see issue #18528). // case extensions.Kind("Deployment"): // return &DeploymentScaler{c.Extensions()}, nil } return nil, fmt.Errorf("no scaler has been implemented for %q", kind) }
func ScalerFor(kind unversioned.GroupKind, c client.Interface) (Scaler, error) { switch kind { case api.Kind("ReplicationController"): return &ReplicationControllerScaler{c}, nil case extensions.Kind("ReplicaSet"): return &ReplicaSetScaler{c.Extensions()}, nil case extensions.Kind("Job"), batch.Kind("Job"): return &JobScaler{c.Batch()}, nil // Either kind of job can be scaled with Batch interface. case apps.Kind("PetSet"): return &PetSetScaler{c.Apps()}, nil case extensions.Kind("Deployment"): return &DeploymentScaler{c.Extensions()}, nil } return nil, fmt.Errorf("no scaler has been implemented for %q", kind) }
// testPodNodeConstraintsObjectCreationWithPodTemplate attemps to create different object types that contain pod templates // using the passed in nodeName and nodeSelector. It will use the expectError flag to determine if an error should be returned or not func testPodNodeConstraintsObjectCreationWithPodTemplate(t *testing.T, name string, kclient kclient.Interface, client client.Interface, nodeName string, nodeSelector map[string]string, expectError bool) { checkForbiddenErr := func(objType string, err error) { if err == nil && expectError { t.Errorf("%s (%s): expected forbidden error but did not receive one", name, objType) return } if err != nil && !expectError { t.Errorf("%s (%s): got error but did not expect one: %v", name, objType, err) return } if err != nil && expectError && !kapierrors.IsForbidden(err) { t.Errorf("%s (%s): did not get an expected forbidden error: %v", name, objType, err) return } } // Pod pod := testPodNodeConstraintsPod(nodeName, nodeSelector) _, err := kclient.Pods(testutil.Namespace()).Create(pod) checkForbiddenErr("pod", err) // ReplicationController rc := testPodNodeConstraintsReplicationController(nodeName, nodeSelector) _, err = kclient.ReplicationControllers(testutil.Namespace()).Create(rc) checkForbiddenErr("rc", err) // TODO: Enable when the deployments endpoint is supported in Origin // Deployment // d := testPodNodeConstraintsDeployment(nodeName, nodeSelector) // _, err = kclient.Extensions().Deployments(testutil.Namespace()).Create(d) // checkForbiddenErr("deployment", err) // ReplicaSet rs := testPodNodeConstraintsReplicaSet(nodeName, nodeSelector) _, err = kclient.Extensions().ReplicaSets(testutil.Namespace()).Create(rs) checkForbiddenErr("replicaset", err) // Job job := testPodNodeConstraintsJob(nodeName, nodeSelector) _, err = kclient.Extensions().Jobs(testutil.Namespace()).Create(job) checkForbiddenErr("job", err) // DeploymentConfig dc := testPodNodeConstraintsDeploymentConfig(nodeName, nodeSelector) _, err = client.DeploymentConfigs(testutil.Namespace()).Create(dc) checkForbiddenErr("dc", err) }
// DeleteDaemonSetServices deletes services related to daemon set with given name in given namespace. func DeleteDaemonSetServices(client k8sClient.Interface, namespace, name string) error { log.Printf("Deleting services related to %s daemon set from %s namespace", name, namespace) daemonSet, err := client.Extensions().DaemonSets(namespace).Get(name) if err != nil { return err } labelSelector, err := unversioned.LabelSelectorAsSelector(daemonSet.Spec.Selector) if err != nil { return err } services, err := getServicesForDSDeletion(client, labelSelector, namespace) if err != nil { return err } for _, service := range services { if err := client.Services(namespace).Delete(service.Name); err != nil { return err } } log.Printf("Successfully deleted services related to %s daemon set from %s namespace", name, namespace) return nil }
// GetReplicaSetDetail gets replica set details. func GetReplicaSetDetail(client k8sClient.Interface, heapsterClient client.HeapsterClient, namespace, name string) (*ReplicaSetDetail, error) { log.Printf("Getting details of %s service in %s namespace", name, namespace) // TODO(floreks): Use channels. replicaSetData, err := client.Extensions().ReplicaSets(namespace).Get(name) if err != nil { return nil, err } eventList, err := GetReplicaSetEvents(client, dataselect.DefaultDataSelect, replicaSetData.Namespace, replicaSetData.Name) if err != nil { return nil, err } podList, err := GetReplicaSetPods(client, heapsterClient, dataselect.DefaultDataSelectWithMetrics, name, namespace) if err != nil { return nil, err } podInfo, err := getReplicaSetPodInfo(client, replicaSetData) if err != nil { return nil, err } serviceList, err := GetReplicaSetServices(client, dataselect.DefaultDataSelect, namespace, name) if err != nil { return nil, err } replicaSet := ToReplicaSetDetail(replicaSetData, *eventList, *podList, *podInfo, *serviceList) return &replicaSet, nil }
// getJobPods returns list of pods targeting deployment. func GetDeploymentPods(client client.Interface, heapsterClient heapster.HeapsterClient, dsQuery *dataselect.DataSelectQuery, namespace string, deploymentName string) (*pod.PodList, error) { deployment, err := client.Extensions().Deployments(namespace).Get(deploymentName) if err != nil { return nil, err } selector, err := unversioned.LabelSelectorAsSelector(deployment.Spec.Selector) if err != nil { return nil, err } options := api.ListOptions{LabelSelector: selector} channels := &common.ResourceChannels{ PodList: common.GetPodListChannelWithOptions(client, common.NewSameNamespaceQuery(namespace), options, 1), } rawPods := <-channels.PodList.List if err := <-channels.PodList.Error; err != nil { return nil, err } pods := common.FilterNamespacedPodsBySelector(rawPods.Items, deployment.ObjectMeta.Namespace, deployment.Spec.Selector.MatchLabels) podList := pod.CreatePodList(pods, dsQuery, heapsterClient) return &podList, nil }
// Returns structure containing DaemonSet and Pods for the given daemon set. func getRawDaemonSetWithPods(client client.Interface, namespace, name string) ( *DaemonSetWithPods, error) { daemonSet, err := client.Extensions().DaemonSets(namespace).Get(name) if err != nil { return nil, err } labelSelector, err := unversioned.LabelSelectorAsSelector(daemonSet.Spec.Selector) if err != nil { return nil, err } pods, err := client.Pods(namespace).List( api.ListOptions{ LabelSelector: labelSelector, FieldSelector: fields.Everything(), }) if err != nil { return nil, err } daemonSetAndPods := &DaemonSetWithPods{ DaemonSet: daemonSet, Pods: pods, } return daemonSetAndPods, nil }
// GetJobDetail gets job details. func GetJobDetail(client k8sClient.Interface, heapsterClient client.HeapsterClient, namespace, name string) (*JobDetail, error) { log.Printf("Getting details of %s service in %s namespace", name, namespace) // TODO(floreks): Use channels. jobData, err := client.Extensions().Jobs(namespace).Get(name) if err != nil { return nil, err } channels := &common.ResourceChannels{ PodList: common.GetPodListChannel(client, common.NewSameNamespaceQuery(namespace), 1), } pods := <-channels.PodList.List if err := <-channels.PodList.Error; err != nil { return nil, err } events, err := GetJobEvents(client, jobData.Namespace, jobData.Name) if err != nil { return nil, err } job := getJobDetail(jobData, heapsterClient, events, pods.Items) return &job, nil }
// GetJobDetail gets job details. func GetJobDetail(client k8sClient.Interface, heapsterClient client.HeapsterClient, namespace, name string) (*JobDetail, error) { // TODO(floreks): Use channels. jobData, err := client.Extensions().Jobs(namespace).Get(name) if err != nil { return nil, err } podList, err := GetJobPods(client, heapsterClient, dataselect.DefaultDataSelectWithMetrics, namespace, name) if err != nil { return nil, err } podInfo, err := getJobPodInfo(client, jobData) if err != nil { return nil, err } eventList, err := GetJobEvents(client, dataselect.DefaultDataSelect, jobData.Namespace, jobData.Name) if err != nil { return nil, err } job := getJobDetail(jobData, heapsterClient, *eventList, *podList, *podInfo) return &job, nil }
// Based on given selector returns list of services that are candidates for deletion. // Services are matched by daemon sets' label selector. They are deleted if given // label selector is targeting only 1 daemon set. func getServicesForDSDeletion(client client.Interface, labelSelector labels.Selector, namespace string) ([]api.Service, error) { daemonSet, err := client.Extensions().DaemonSets(namespace).List(api.ListOptions{ LabelSelector: labelSelector, FieldSelector: fields.Everything(), }) if err != nil { return nil, err } // if label selector is targeting only 1 daemon set // then we can delete services targeted by this label selector, // otherwise we can not delete any services so just return empty list if len(daemonSet.Items) != 1 { return []api.Service{}, nil } services, err := client.Services(namespace).List(api.ListOptions{ LabelSelector: labelSelector, FieldSelector: fields.Everything(), }) if err != nil { return nil, err } return services.Items, nil }
// GetDeploymentEvents returns model events for a deployment with the given name in the given // namespace func GetDeploymentEvents(client client.Interface, dsQuery *dataselect.DataSelectQuery, namespace string, deploymentName string) ( *common.EventList, error) { deployment, err := client.Extensions().Deployments(namespace).Get(deploymentName) if err != nil { return nil, err } selector, err := unversioned.LabelSelectorAsSelector(deployment.Spec.Selector) if err != nil { return nil, err } options := api.ListOptions{LabelSelector: selector} channels := &common.ResourceChannels{ EventList: common.GetEventListChannelWithOptions(client, common.NewSameNamespaceQuery(namespace), options, 1), } eventRaw := <-channels.EventList.List if err := <-channels.EventList.Error; err != nil { return nil, err } dpEvents := eventRaw.Items if !event.IsTypeFilled(dpEvents) { dpEvents = event.FillEventsType(dpEvents) } eventList := event.CreateEventList(dpEvents, dsQuery) return &eventList, nil }
// GetIngressList - return all ingresses in the given namespace. func GetIngressList(client client.Interface, namespace *common.NamespaceQuery, dsQuery *dataselect.DataSelectQuery) (*IngressList, error) { ingressList, err := client.Extensions().Ingress(namespace.ToRequestParam()).List(api.ListOptions{ LabelSelector: labels.Everything(), FieldSelector: fields.Everything(), }) if err != nil { return nil, err } return NewIngressList(ingressList.Items, dsQuery), err }
// GetIngressDetail returns returns detailed information about a ingress func GetIngressDetail(client client.Interface, namespace, name string) (*IngressDetail, error) { log.Printf("Getting details of %s ingress in %s namespace", name, namespace) rawIngress, err := client.Extensions().Ingress(namespace).Get(name) if err != nil { return nil, err } return getIngressDetail(rawIngress), nil }
func New(client client.Interface) *DeploymentController { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) eventBroadcaster.StartRecordingToSink(client.Events("")) return &DeploymentController{ client: client, expClient: client.Extensions(), eventRecorder: eventBroadcaster.NewRecorder(api.EventSource{Component: "deployment-controller"}), } }
// GetJobList returns a list of all Jobs in the cluster. func GetJobList(client client.Interface, nsQuery *common.NamespaceQuery) (*JobList, error) { log.Printf("Getting list of all jobs in the cluster") channels := &common.ResourceChannels{ JobList: common.GetJobListChannel(client.Extensions(), nsQuery, 1), PodList: common.GetPodListChannel(client, nsQuery, 1), EventList: common.GetEventListChannel(client, nsQuery, 1), } return GetJobListFromChannels(channels) }
func toJobPodController(client k8sClient.Interface, reference api.ObjectReference, pods []api.Pod, events []api.Event, heapsterClient client.HeapsterClient) (*Controller, error) { job, err := client.Extensions().Jobs(reference.Namespace).Get(reference.Name) if err != nil { return nil, err } jobs := []batch.Job{*job} jobList := joblist.CreateJobList(jobs, pods, events, dataselect.StdMetricsDataSelect, &heapsterClient) return &Controller{ Kind: "Job", JobList: jobList, }, nil }
func toReplicaSetPodController(client k8sClient.Interface, reference api.ObjectReference, pods []api.Pod, events []api.Event, heapsterClient client.HeapsterClient) (*Controller, error) { rs, err := client.Extensions().ReplicaSets(reference.Namespace).Get(reference.Name) if err != nil { return nil, err } replicaSets := []extensions.ReplicaSet{*rs} replicaSetList := replicasetlist.CreateReplicaSetList(replicaSets, pods, events, dataselect.StdMetricsDataSelect, &heapsterClient) return &Controller{ Kind: "ReplicaSet", ReplicaSetList: replicaSetList, }, nil }
// GetReplicaSetList returns a list of all Replica Sets in the cluster. func GetReplicaSetList(client client.Interface, nsQuery *common.NamespaceQuery, dsQuery *dataselect.DataSelectQuery, heapsterClient *heapster.HeapsterClient) (*ReplicaSetList, error) { log.Printf("Getting list of all replica sets in the cluster") channels := &common.ResourceChannels{ ReplicaSetList: common.GetReplicaSetListChannel(client.Extensions(), nsQuery, 1), PodList: common.GetPodListChannel(client, nsQuery, 1), EventList: common.GetEventListChannel(client, nsQuery, 1), } return GetReplicaSetListFromChannels(channels, dsQuery, heapsterClient) }
func toDaemonSetPodController(client k8sClient.Interface, reference api.ObjectReference, pods []api.Pod, events []api.Event, heapsterClient client.HeapsterClient) (*Controller, error) { daemonset, err := client.Extensions().DaemonSets(reference.Namespace).Get(reference.Name) if err != nil { return nil, err } daemonsets := []extensions.DaemonSet{*daemonset} daemonSetList := daemonsetlist.CreateDaemonSetList(daemonsets, pods, events, dataselect.StdMetricsDataSelect, &heapsterClient) return &Controller{ Kind: "DaemonSet", DaemonSetList: daemonSetList, }, nil }
// GetDaemonSetPodsEvents gets events associated to pods in daemon set. func GetDaemonSetPodsEvents(client client.Interface, namespace, daemonSetName string) ( []api.Event, error) { daemonSet, err := client.Extensions().DaemonSets(namespace).Get(daemonSetName) if err != nil { return nil, err } podEvents, err := event.GetPodsEvents(client, namespace, daemonSet.Spec.Selector.MatchLabels) if err != nil { return nil, err } return podEvents, nil }
// Returns detailed information about the given daemon set in the given namespace. func GetDaemonSetDetail(client k8sClient.Interface, heapsterClient client.HeapsterClient, namespace, name string) (*DaemonSetDetail, error) { log.Printf("Getting details of %s daemon set in %s namespace", name, namespace) daemonSet, err := client.Extensions().DaemonSets(namespace).Get(name) if err != nil { return nil, err } podList, err := GetDaemonSetPods(client, heapsterClient, dataselect.DefaultDataSelectWithMetrics, name, namespace) if err != nil { return nil, err } podInfo, err := getDaemonSetPodInfo(client, daemonSet) if err != nil { return nil, err } serviceList, err := GetDaemonSetServices(client, dataselect.DefaultDataSelect, namespace, name) if err != nil { return nil, err } eventList, err := GetDaemonSetEvents(client, dataselect.DefaultDataSelect, daemonSet.Namespace, daemonSet.Name) if err != nil { return nil, err } daemonSetDetail := &DaemonSetDetail{ ObjectMeta: common.NewObjectMeta(daemonSet.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindDaemonSet), LabelSelector: daemonSet.Spec.Selector, PodInfo: *podInfo, PodList: *podList, ServiceList: *serviceList, EventList: *eventList, } for _, container := range daemonSet.Spec.Template.Spec.Containers { daemonSetDetail.ContainerImages = append(daemonSetDetail.ContainerImages, container.Image) } return daemonSetDetail, nil }
// GetJobPodsEvents gets events associated to pods in job. func GetJobPodsEvents(client client.Interface, namespace, jobName string) ( []api.Event, error) { job, err := client.Extensions().Jobs(namespace).Get(jobName) if err != nil { return nil, err } podEvents, err := event.GetPodsEvents(client, namespace, job.Spec.Selector.MatchLabels) if err != nil { return nil, err } return podEvents, nil }
// Returns array of api pods targeting daemon set with given name. func getRawDaemonSetPods(client k8sClient.Interface, daemonSetName, namespace string) ( []api.Pod, error) { daemonSet, err := client.Extensions().DaemonSets(namespace).Get(daemonSetName) if err != nil { return nil, err } channels := &common.ResourceChannels{ PodList: common.GetPodListChannel(client, common.NewSameNamespaceQuery(namespace), 1), } podList := <-channels.PodList.List if err := <-channels.PodList.Error; err != nil { return nil, err } matchingPods := common.FilterNamespacedPodsByLabelSelector(podList.Items, daemonSet.ObjectMeta.Namespace, daemonSet.Spec.Selector) return matchingPods, nil }
// GetDaemonSetServices returns list of services that are related to daemon set targeted by given // name. func GetDaemonSetServices(client client.Interface, dsQuery *dataselect.DataSelectQuery, namespace, name string) (*service.ServiceList, error) { daemonSet, err := client.Extensions().DaemonSets(namespace).Get(name) if err != nil { return nil, err } channels := &common.ResourceChannels{ ServiceList: common.GetServiceListChannel(client, common.NewSameNamespaceQuery(namespace), 1), } services := <-channels.ServiceList.List if err := <-channels.ServiceList.Error; err != nil { return nil, err } matchingServices := common.FilterNamespacedServicesBySelector(services.Items, namespace, daemonSet.Spec.Selector.MatchLabels) return service.CreateServiceList(matchingServices, dsQuery), nil }