github.com/jlmeeker/kismatic@v1.10.1-0.20180612190640-57f9005a1f1a/pkg/data/kubernetes.go (about)

     1  package data
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/apprenda/kismatic/pkg/ssh"
     9  )
    10  
    11  // PodLister lists pods on a Kubernetes cluster
    12  type PodLister interface {
    13  	ListPods() (*PodList, error)
    14  }
    15  
    16  // PVLister lists persistent volumes that exist on a Kubernetes cluster
    17  type PVLister interface {
    18  	ListPersistentVolumes() (*PersistentVolumeList, error)
    19  }
    20  
    21  // PersistentVolumeGetter gets a persistent volume
    22  type PersistentVolumeGetter interface {
    23  	GetPersistentVolume(name string) (*PersistentVolume, error)
    24  }
    25  
    26  // PersistentVolumeClaimGetter gets a persistent volume claim
    27  type PersistentVolumeClaimGetter interface {
    28  	GetPersistentVolumeClaim(namespace, name string) (*PersistentVolumeClaim, error)
    29  }
    30  
    31  // DaemonSetGetter gets a given daemonset
    32  type DaemonSetGetter interface {
    33  	GetDaemonSet(namespace, name string) (*DaemonSet, error)
    34  }
    35  
    36  // ReplicationControllerGetter gets a replication controller
    37  type ReplicationControllerGetter interface {
    38  	GetReplicationController(namespace, name string) (*ReplicationController, error)
    39  }
    40  
    41  // ReplicaSetGetter gets a replica set
    42  type ReplicaSetGetter interface {
    43  	GetReplicaSet(namespace, name string) (*ReplicaSet, error)
    44  }
    45  
    46  // StatefulSetGetter gets a stateful set
    47  type StatefulSetGetter interface {
    48  	GetStatefulSet(namespace, name string) (*StatefulSet, error)
    49  }
    50  
    51  type KubernetesClient interface {
    52  	PodLister
    53  	PVLister
    54  }
    55  
    56  // RemoteKubectl is a kubectl client that uses an underlying SSH connection
    57  // to connect to a node that has the kubectl binary. It is expected that this
    58  // node has access to a kubernetes cluster via kubectl.
    59  type RemoteKubectl struct {
    60  	SSHClient ssh.Client
    61  }
    62  
    63  // ListPersistentVolumes returns PersistentVolume data
    64  func (k RemoteKubectl) ListPersistentVolumes() (*PersistentVolumeList, error) {
    65  	pvRaw, err := k.SSHClient.Output(true, "sudo kubectl --kubeconfig /root/.kube/config get pv -o json")
    66  	if err != nil {
    67  		return nil, fmt.Errorf("error getting persistent volume data: %v", err)
    68  	}
    69  	return UnmarshalPVs(pvRaw)
    70  }
    71  
    72  func UnmarshalPVs(raw string) (*PersistentVolumeList, error) {
    73  	if isNoResourcesResponse(raw) {
    74  		return nil, nil
    75  	}
    76  	var pvs PersistentVolumeList
    77  	err := json.Unmarshal([]byte(raw), &pvs)
    78  	if err != nil {
    79  		return nil, fmt.Errorf("error unmarshalling persistent volume data: %v", err)
    80  	}
    81  	return &pvs, nil
    82  }
    83  
    84  // ListPods returns Pods data with --all-namespaces=true flag
    85  func (k RemoteKubectl) ListPods() (*PodList, error) {
    86  	podsRaw, err := k.SSHClient.Output(true, "sudo kubectl --kubeconfig /root/.kube/config get pods --all-namespaces=true -o json")
    87  	if err != nil {
    88  		return nil, fmt.Errorf("error getting pod data: %v", err)
    89  	}
    90  	return UnmarshalPods(podsRaw)
    91  }
    92  
    93  func UnmarshalPods(raw string) (*PodList, error) {
    94  	if isNoResourcesResponse(raw) {
    95  		return nil, nil
    96  	}
    97  	var pods PodList
    98  	err := json.Unmarshal([]byte(raw), &pods)
    99  	if err != nil {
   100  		return nil, fmt.Errorf("error unmarshalling pod data: %v", err)
   101  	}
   102  	return &pods, nil
   103  }
   104  
   105  // GetDaemonSet returns the DaemonSet with the given namespace and name. If not found,
   106  // returns an error.
   107  func (k RemoteKubectl) GetDaemonSet(namespace, name string) (*DaemonSet, error) {
   108  	cmd := fmt.Sprintf("sudo kubectl --kubeconfig /root/.kube/config get ds --namespace=%s -o json %s", namespace, name)
   109  	dsRaw, err := k.SSHClient.Output(true, cmd)
   110  	if err != nil {
   111  		return nil, fmt.Errorf("error getting daemon sets: %v", err)
   112  	}
   113  	if isNoResourcesResponse(dsRaw) {
   114  		return nil, fmt.Errorf("DaemonSet %s/%s was not found", namespace, name)
   115  	}
   116  	var d DaemonSet
   117  	if err := json.Unmarshal([]byte(dsRaw), &d); err != nil {
   118  		return nil, fmt.Errorf("error unmarshalling daemonset: %v", err)
   119  	}
   120  	return &d, nil
   121  }
   122  
   123  // GetReplicationController returns the ReplicationController with the given name in the given namespace.
   124  // If not found, returns an error.
   125  func (k RemoteKubectl) GetReplicationController(namespace, name string) (*ReplicationController, error) {
   126  	cmd := fmt.Sprintf("sudo kubectl --kubeconfig /root/.kube/config get replicationcontroller --namespace=%s -o json %s", namespace, name)
   127  	rcRaw, err := k.SSHClient.Output(true, cmd)
   128  	if err != nil {
   129  		return nil, fmt.Errorf("error getting replication controller: %v", err)
   130  	}
   131  	if isNoResourcesResponse(rcRaw) {
   132  		return nil, fmt.Errorf("ReplicationController %s/%s was not found", namespace, name)
   133  	}
   134  	var r ReplicationController
   135  	if err := json.Unmarshal([]byte(rcRaw), &r); err != nil {
   136  		return nil, fmt.Errorf("error unmarshalling replication controller: %v", err)
   137  	}
   138  	return &r, nil
   139  }
   140  
   141  // GetReplicaSet returns the ReplicaSet with the given name in the given namespace.
   142  // If not found, returns an error.
   143  func (k RemoteKubectl) GetReplicaSet(namespace, name string) (*ReplicaSet, error) {
   144  	cmd := fmt.Sprintf("sudo kubectl --kubeconfig /root/.kube/config get replicaset --namespace=%s -o json %s", namespace, name)
   145  	raw, err := k.SSHClient.Output(true, cmd)
   146  	if err != nil {
   147  		return nil, fmt.Errorf("error getting ReplicaSet: %v", err)
   148  	}
   149  	if isNoResourcesResponse(raw) {
   150  		return nil, fmt.Errorf("ReplicaSet %s/%s was not found", namespace, name)
   151  	}
   152  	var r ReplicaSet
   153  	if err := json.Unmarshal([]byte(raw), &r); err != nil {
   154  		return nil, fmt.Errorf("error unmarshalling ReplicaSet: %v", err)
   155  	}
   156  	return &r, nil
   157  }
   158  
   159  // GetPersistentVolume returns the persistent volume with the given name.
   160  // If not found, returns an error.
   161  func (k RemoteKubectl) GetPersistentVolume(name string) (*PersistentVolume, error) {
   162  	cmd := fmt.Sprintf("sudo kubectl --kubeconfig /root/.kube/config get pv -o json %s", name)
   163  	raw, err := k.SSHClient.Output(true, cmd)
   164  	if err != nil {
   165  		return nil, fmt.Errorf("error getting PersistentVolume: %v", err)
   166  	}
   167  	if isNoResourcesResponse(raw) {
   168  		return nil, fmt.Errorf("PersistentVolume %s was not found", name)
   169  	}
   170  	var p PersistentVolume
   171  	if err := json.Unmarshal([]byte(raw), &p); err != nil {
   172  		return nil, fmt.Errorf("error unmarshalling PersistentVolume: %v", err)
   173  	}
   174  	return &p, nil
   175  }
   176  
   177  // GetPersistentVolumeClaim returns the persistent volume claim with the given name and namespace.
   178  // If not found, returns an error.
   179  func (k RemoteKubectl) GetPersistentVolumeClaim(namespace, name string) (*PersistentVolumeClaim, error) {
   180  	cmd := fmt.Sprintf("sudo kubectl --kubeconfig /root/.kube/config get pvc --namespace %s -o json %s", namespace, name)
   181  	raw, err := k.SSHClient.Output(true, cmd)
   182  	if err != nil {
   183  		return nil, fmt.Errorf("error getting PersistentVolumeClaim: %v", err)
   184  	}
   185  	if isNoResourcesResponse(raw) {
   186  		return nil, fmt.Errorf("PersistentVolumeClaim %s was not found", name)
   187  	}
   188  	var p PersistentVolumeClaim
   189  	if err := json.Unmarshal([]byte(raw), &p); err != nil {
   190  		return nil, fmt.Errorf("error unmarshalling PersistentVolumeClaim: %v", err)
   191  	}
   192  	return &p, nil
   193  }
   194  
   195  // GetStatefulSet returns the stateful set with the given name in the given namespace.
   196  // If not found, returns an error.
   197  func (k RemoteKubectl) GetStatefulSet(namespace, name string) (*StatefulSet, error) {
   198  	cmd := fmt.Sprintf("sudo kubectl --kubeconfig /root/.kube/config get statefulset --namespace %s -o json %s", namespace, name)
   199  	raw, err := k.SSHClient.Output(true, cmd)
   200  	if err != nil {
   201  		return nil, fmt.Errorf("error getting StatefulSet: %v", err)
   202  	}
   203  	if isNoResourcesResponse(raw) {
   204  		return nil, fmt.Errorf("StatefulSet %s/%s was not found", namespace, name)
   205  	}
   206  	var s StatefulSet
   207  	if err := json.Unmarshal([]byte(raw), &s); err != nil {
   208  		return nil, fmt.Errorf("error unmarshalling StatefulSet: %v", err)
   209  	}
   210  	return &s, nil
   211  }
   212  
   213  // kubectl will print this message when no resources are returned
   214  func isNoResourcesResponse(s string) bool {
   215  	if strings.Contains(strings.TrimSpace(s), "No resources found") {
   216  		return true
   217  	}
   218  	return false
   219  }