"helm status" add the filter of kind and instance name. Add the desrcibe of pod.

pull/2411/head
devinyan 9 years ago
parent 43a7ed6bb0
commit 7096d16fe6

@ -154,6 +154,10 @@ message GetReleaseStatusRequest {
string name = 1; string name = 1;
// Version is the version of the release // Version is the version of the release
int32 version = 2; int32 version = 2;
// Kind is the kind of the resource to display
string kind = 3;
// Instance is the instance of the resource to display
string instance = 4;
} }
// GetReleaseStatusResponse is the response indicating the status of the named release. // GetReleaseStatusResponse is the response indicating the status of the named release.

@ -47,7 +47,9 @@ type statusCmd struct {
release string release string
out io.Writer out io.Writer
client helm.Interface client helm.Interface
version int32 kind string
instance string
version int32
} }
func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command { func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command {
@ -73,13 +75,18 @@ func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command {
}, },
} }
cmd.PersistentFlags().StringVar(&status.instance, "instance","","if set, display status of an instance in assigned kind.")
cmd.PersistentFlags().StringVar(&status.kind, "kind","","if set, display status of an assigned kind resource")
cmd.PersistentFlags().Int32Var(&status.version, "revision", 0, "if set, display the status of the named release with revision") cmd.PersistentFlags().Int32Var(&status.version, "revision", 0, "if set, display the status of the named release with revision")
return cmd return cmd
} }
func (s *statusCmd) run() error { func (s *statusCmd) run() error {
res, err := s.client.ReleaseStatus(s.release, helm.StatusReleaseVersion(s.version))
fmt.Printf("Kind=%s,instnace=%s",s.kind,s.instance)
res, err := s.client.ReleaseStatus(s.release, helm.StatusReleaseVersion(s.version,s.kind,s.instance))
if err != nil { if err != nil {
return prettyError(err) return prettyError(err)
} }

@ -29,6 +29,9 @@ helm status [flags] RELEASE_NAME
--tls-cert string path to TLS certificate file (default "$HELM_HOME/cert.pem") --tls-cert string path to TLS certificate file (default "$HELM_HOME/cert.pem")
--tls-key string path to TLS key file (default "$HELM_HOME/key.pem") --tls-key string path to TLS key file (default "$HELM_HOME/key.pem")
--tls-verify enable TLS for request and verify remote --tls-verify enable TLS for request and verify remote
--kind string if set, display status of an assigned kind resource (The kind of resorce is kubeneters
resource such as : service,ingress,deployment,pod,replicaset and so on)
--instance string if set, display status of an instance in assigned kind.(The paramater must along with "--kind")
``` ```
### Options inherited from parent commands ### Options inherited from parent commands

@ -371,9 +371,11 @@ type StatusOption func(*options)
// StatusReleaseVersion will instruct Tiller to retrieve the status // StatusReleaseVersion will instruct Tiller to retrieve the status
// of a particular version of a release. // of a particular version of a release.
func StatusReleaseVersion(version int32) StatusOption { func StatusReleaseVersion(version int32,kind string,instance string) StatusOption {
return func(opts *options) { return func(opts *options) {
opts.statusReq.Version = version opts.statusReq.Version = version
opts.statusReq.Kind = kind
opts.statusReq.Instance = instance
} }
} }

@ -145,32 +145,65 @@ func (c *Client) Build(namespace string, reader io.Reader) (Result, error) {
// Get gets kubernetes resources as pretty printed string // Get gets kubernetes resources as pretty printed string
// //
// Namespace will set the namespace // Namespace will set the namespace
func (c *Client) Get(namespace string, reader io.Reader) (string, error) { func (c *Client) Get(namespace string, reader io.Reader, filter FilterStruct) (string, error) {
// Since we don't know what order the objects come in, let's group them by the types, so // Since we don't know what order the objects come in, let's group them by the types, so
// that when we print them, they come looking good (headers apply to subgroups, etc.) // that when we print them, they come looking good (headers apply to subgroups, etc.)
objs := make(map[string][]runtime.Object) objs := make(map[string][]runtime.Object)
infos, err := c.BuildUnstructured(namespace, reader)
infoAllKinds, err := c.BuildUnstructured(namespace, reader)
if err != nil { if err != nil {
return "", err return "", err
} }
infos := infoAllKinds.Filter(filter.Filter)
var objPods map[string][]api.Pod
if (!filter.IsFilter()) || filter.IsPodType() {
objPods = c.getRelationPods(infoAllKinds)
}
log.Printf("objPods %+v\n", objPods)
missing := []string{} missing := []string{}
err = perform(infos, func(info *resource.Info) error { if len(infos) !=0 {
log.Printf("Doing get for %s: %q", info.Mapping.GroupVersionKind.Kind, info.Name) err = perform(infos, func(info *resource.Info) error {
if err := info.Get(); err != nil {
log.Printf("WARNING: Failed Get for resource %q: %s", info.Name, err) if err := info.Get(); err != nil {
missing = append(missing, fmt.Sprintf("%v\t\t%s", info.Mapping.Resource, info.Name)) log.Printf("WARNING: Failed Get for resource %q: %s", info.Name, err)
missing = append(missing, fmt.Sprintf("%v\t\t%s", info.Mapping.Resource, info.Name))
return nil
}
// Use APIVersion/Kind as grouping mechanism. I'm not sure if you can have multiple
// versions per cluster, but this certainly won't hurt anything, so let's be safe.
gvk := info.ResourceMapping().GroupVersionKind
vk := gvk.Version + "/" + gvk.Kind
if gvk.Kind != "Pod" {
objs[vk] = append(objs[vk], info.Object)
} else {
if !IsFoundPodInfo(objPods[vk], info) {
objs[vk] = append(objs[vk], info.Object)
}
}
return nil return nil
})
if err != nil {
return "", err
}
}else{
if !filter.IsFilter(){
return "",ErrNoObjectsVisited
}else if (!filter.IsPodType()) || (len(objPods) == 0) {
return "",nil
} }
}
// Use APIVersion/Kind as grouping mechanism. I'm not sure if you can have multiple //here, we will add the objPods to the objs
// versions per cluster, but this certainly won't hurt anything, so let's be safe. for key,podItems := range objPods{
gvk := info.ResourceMapping().GroupVersionKind for _,pod := range podItems {
vk := gvk.Version + "/" + gvk.Kind objs[key] = append(objs[key],&pod)
objs[vk] = append(objs[vk], info.Object) }
return nil
})
if err != nil {
return "", err
} }
// Ok, now we have all the objects grouped by types (say, by v1/Pod, v1/Service, etc.), so // Ok, now we have all the objects grouped by types (say, by v1/Pod, v1/Service, etc.), so
@ -595,3 +628,89 @@ func watchPodUntilComplete(timeout time.Duration, info *resource.Info) error {
return err return err
} }
func (c *Client) getRelationPods(infos []*resource.Info)(map[string][]api.Pod){
var objPods = make(map[string][]api.Pod)
for _, value := range infos {
objPods , _ = c.getSelectRelationPod(value,objPods)
}
return objPods
}
func (c *Client) getSelectRelationPod(info *resource.Info,objPods map[string][]api.Pod)(map[string][]api.Pod,error){
log.Printf("1222getSelectRelationPod Info: %+v",info)
log.Printf("222222getSelectRelationPod object: %+v",info.Object)
err := info.Get()
if err != nil {
return objPods, err
}
log.Printf("getSelectRelationPod object: %+v",info.Object)
versioned, err := c.AsVersionedObject(info.Object)
if runtime.IsNotRegisteredError(err) {
return objPods,nil
}
if err != nil {
return objPods,err
}
selector, err := getSelectorFromObject(versioned)
log.Printf("getSelectRelationPod selector: %+v",selector)
if err != nil {
return objPods,err
}
client, _ := c.ClientSet()
pods, err := client.Core().Pods(info.Namespace).List(metav1.ListOptions{
FieldSelector: fields.Everything().String(),
LabelSelector: labels.Set(selector).AsSelector().String(),
})
if err != nil {
return objPods,err
}
for _, pod := range pods.Items {
log.Printf("get select relation pod: %v/%v", pod.Namespace, pod.Name)
if pod.APIVersion == "" {
pod.APIVersion = "v1"
}
if pod.Kind == "" {
pod.Kind = "Pod"
}
vk := pod.GroupVersionKind().Version + "/" + pod.GroupVersionKind().Kind
if !IsFoundPod(objPods[vk], pod) {
objPods[vk] = append(objPods[vk], pod)
}
}
return objPods,nil
}
func IsFoundPod(podItem []api.Pod,pod api.Pod) bool {
for _,value := range podItem {
if (value.Namespace == pod.Namespace) && (value.Name==pod.Name) {
return true
}
}
return false
}
func IsFoundPodInfo(podItem []api.Pod,podInfo *resource.Info) bool {
for _, value := range podItem {
if (value.Namespace == podInfo.Namespace) && (value.Name == podInfo.Name) {
return true
}
}
return false
}

@ -21,6 +21,35 @@ import "k8s.io/kubernetes/pkg/kubectl/resource"
// Result provides convenience methods for comparing collections of Infos. // Result provides convenience methods for comparing collections of Infos.
type Result []*resource.Info type Result []*resource.Info
type FilterStruct struct {
Kind string
Instance string
}
func (fs *FilterStruct) Filter (info *resource.Info) bool{
if info != nil {
if (fs.Kind == "") || (fs.Kind == info.Mapping.GroupVersionKind.Kind) {
if (fs.Instance == "") || (fs.Instance == info.Name) {
return true
}
}
}
return false
}
func (fs *FilterStruct) IsFilter() bool{
if (fs.Kind == "") && (fs.Instance == "") {
return false
}
return true
}
func (fs *FilterStruct) IsPodType() bool {
if (fs.Kind == "Pod") {
return true
}
return false
}
// Append adds an Info to the Result. // Append adds an Info to the Result.
func (r *Result) Append(val *resource.Info) { func (r *Result) Append(val *resource.Info) {
*r = append(*r, val) *r = append(*r, val)

@ -123,7 +123,7 @@ type KubeClient interface {
// //
// reader must contain a YAML stream (one or more YAML documents separated // reader must contain a YAML stream (one or more YAML documents separated
// by "\n---\n"). // by "\n---\n").
Get(namespace string, reader io.Reader) (string, error) Get(namespace string, reader io.Reader, filter kube.FilterStruct) (string, error)
// Delete destroys one or more resources. // Delete destroys one or more resources.
// //

@ -70,8 +70,8 @@ func (m *LocalReleaseModule) Rollback(current, target *release.Release, req *ser
} }
// Status returns kubectl-like formatted status of release objects // Status returns kubectl-like formatted status of release objects
func (m *LocalReleaseModule) Status(r *release.Release, req *services.GetReleaseStatusRequest, env *environment.Environment) (string, error) { func (m *LocalReleaseModule) Status(r *release.Release, req *services.GetReleaseStatusRequest, env *environment.Environment, filter kube.FilterStruct) (string, error) {
return env.KubeClient.Get(r.Namespace, bytes.NewBufferString(r.Manifest)) return env.KubeClient.Get(r.Namespace, bytes.NewBufferString(r.Manifest),filter)
} }
// Delete deletes the release and returns manifests that were kept in the deletion process // Delete deletes the release and returns manifests that were kept in the deletion process
@ -120,7 +120,7 @@ func (m *RemoteReleaseModule) Rollback(current, target *release.Release, req *se
} }
// Status returns status retrieved from rudder.ReleaseStatus // Status returns status retrieved from rudder.ReleaseStatus
func (m *RemoteReleaseModule) Status(r *release.Release, req *services.GetReleaseStatusRequest, env *environment.Environment) (string, error) { func (m *RemoteReleaseModule) Status(r *release.Release, req *services.GetReleaseStatusRequest, env *environment.Environment, filter kube.FilterStruct) (string, error) {
statusRequest := &rudderAPI.ReleaseStatusRequest{Release: r} statusRequest := &rudderAPI.ReleaseStatusRequest{Release: r}
resp, err := rudder.ReleaseStatus(statusRequest) resp, err := rudder.ReleaseStatus(statusRequest)
return resp.Info.Status.Resources, err return resp.Info.Status.Resources, err

@ -41,6 +41,7 @@ import (
"k8s.io/helm/pkg/tiller/environment" "k8s.io/helm/pkg/tiller/environment"
"k8s.io/helm/pkg/timeconv" "k8s.io/helm/pkg/timeconv"
"k8s.io/helm/pkg/version" "k8s.io/helm/pkg/version"
"k8s.io/helm/pkg/kube"
) )
// releaseNameMaxLen is the maximum length of a release name. // releaseNameMaxLen is the maximum length of a release name.
@ -261,9 +262,13 @@ func (s *ReleaseServer) GetReleaseStatus(c ctx.Context, req *services.GetRelease
Info: rel.Info, Info: rel.Info,
} }
var filter kube.FilterStruct = kube.FilterStruct{Kind:req.Kind,Instance:req.Instance}
// Ok, we got the status of the release as we had jotted down, now we need to match the // Ok, we got the status of the release as we had jotted down, now we need to match the
// manifest we stashed away with reality from the cluster. // manifest we stashed away with reality from the cluster.
resp, err := s.ReleaseModule.Status(rel, req, s.env) resp, err := s.ReleaseModule.Status(rel, req, s.env,filter)
if sc == release.Status_DELETED || sc == release.Status_FAILED { if sc == release.Status_DELETED || sc == release.Status_FAILED {
// Skip errors if this is already deleted or failed. // Skip errors if this is already deleted or failed.
return statusResp, nil return statusResp, nil

Loading…
Cancel
Save