github.com/mirantis/virtlet@v1.5.2-0.20191204181327-1659b8a48e9b/pkg/tools/diag_test.go (about)

     1  /*
     2  Copyright 2018 Mirantis
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package tools
    18  
    19  import (
    20  	"bytes"
    21  	"io/ioutil"
    22  	"os"
    23  	"reflect"
    24  	"strings"
    25  	"testing"
    26  
    27  	"github.com/davecgh/go-spew/spew"
    28  
    29  	"github.com/Mirantis/virtlet/pkg/diag"
    30  	testutils "github.com/Mirantis/virtlet/pkg/utils/testing"
    31  	"github.com/Mirantis/virtlet/tests/gm"
    32  )
    33  
    34  var (
    35  	fakeDiagResults = []diag.Result{
    36  		{
    37  			Name:  "diagnostics",
    38  			IsDir: true,
    39  			Children: map[string]diag.Result{
    40  				"foo": {
    41  					Name: "foo",
    42  					Ext:  "txt",
    43  					Data: "foobar",
    44  				},
    45  			},
    46  		},
    47  		{
    48  			Name:  "diagnostics",
    49  			IsDir: true,
    50  			Children: map[string]diag.Result{
    51  				"r1": {
    52  					Name: "r1",
    53  					Ext:  "log",
    54  					Data: "baz1",
    55  				},
    56  				"r2": {
    57  					Name: "r2",
    58  					Ext:  "log",
    59  					Data: "baz2",
    60  				},
    61  			},
    62  		},
    63  	}
    64  	expectedDiagResult = diag.Result{
    65  		Name:  "nodes",
    66  		IsDir: true,
    67  		Children: map[string]diag.Result{
    68  			"kube-node-1": {
    69  				Name:  "kube-node-1",
    70  				IsDir: true,
    71  				Children: map[string]diag.Result{
    72  					"foo": fakeDiagResults[0].Children["foo"],
    73  					"virtlet-pod-virtlet": {
    74  						Name: "virtlet-pod-virtlet",
    75  						Ext:  "log",
    76  						Data: "foo-logs-virtlet",
    77  					},
    78  					"virtlet-pod-libvirt": {
    79  						Name: "virtlet-pod-libvirt",
    80  						Ext:  "log",
    81  						Data: "foo-logs-libvirt",
    82  					},
    83  				},
    84  			},
    85  			"kube-node-2": {
    86  				Name:  "kube-node-2",
    87  				IsDir: true,
    88  				Children: map[string]diag.Result{
    89  					"r1": fakeDiagResults[1].Children["r1"],
    90  					"r2": fakeDiagResults[1].Children["r2"],
    91  					"virtlet-pod-virtlet": {
    92  						Name: "virtlet-pod-virtlet",
    93  						Ext:  "log",
    94  						Data: "bar-logs-virtlet",
    95  					},
    96  					"virtlet-pod-libvirt": {
    97  						Name: "virtlet-pod-libvirt",
    98  						Ext:  "log",
    99  						Data: "bar-logs-libvirt",
   100  					},
   101  				},
   102  			},
   103  		},
   104  	}
   105  	expectedDiagFiles = map[string]interface{}{
   106  		"nodes": map[string]interface{}{
   107  			"kube-node-1": map[string]interface{}{
   108  				"foo.txt":                 "foobar",
   109  				"virtlet-pod-virtlet.log": "foo-logs-virtlet",
   110  				"virtlet-pod-libvirt.log": "foo-logs-libvirt",
   111  			},
   112  			"kube-node-2": map[string]interface{}{
   113  				"r1.log":                  "baz1",
   114  				"r2.log":                  "baz2",
   115  				"virtlet-pod-virtlet.log": "bar-logs-virtlet",
   116  				"virtlet-pod-libvirt.log": "bar-logs-libvirt",
   117  			},
   118  		},
   119  	}
   120  	fakeSonobuoyYaml = `
   121  ---
   122  apiVersion: v1
   123  kind: Service
   124  metadata:
   125    labels:
   126      component: sonobuoy
   127      run: sonobuoy-master
   128    name: sonobuoy-master
   129    namespace: heptio-sonobuoy
   130  spec:
   131    ports:
   132    - port: 8080
   133      protocol: TCP
   134      targetPort: 8080
   135    selector:
   136      run: sonobuoy-master
   137    type: ClusterIP
   138  ---
   139  kind: ConfigMap
   140  apiVersion: v1
   141  metadata:
   142    labels:
   143      component: sonobuoy
   144    name: sonobuoy-plugins-cm
   145    namespace: heptio-sonobuoy
   146  data:
   147    e2e.yaml: |
   148      sonobuoy-config:
   149        driver: Job
   150        plugin-name: e2e
   151        result-type: e2e
   152      spec:
   153        name: e2e
   154  `
   155  )
   156  
   157  func runDiagDumpCommand(t *testing.T, input string, args ...string) []byte {
   158  	c := &fakeKubeClient{
   159  		t: t,
   160  		virtletPods: map[string]string{
   161  			"kube-node-1": "virtlet-foo42",
   162  			"kube-node-2": "virtlet-bar42",
   163  		},
   164  		logs: map[string]string{
   165  			"virtlet-foo42/virtlet/kube-system": "foo-logs-virtlet",
   166  			"virtlet-foo42/libvirt/kube-system": "foo-logs-libvirt",
   167  			"virtlet-bar42/virtlet/kube-system": "bar-logs-virtlet",
   168  			"virtlet-bar42/libvirt/kube-system": "bar-logs-libvirt",
   169  		},
   170  		expectedCommands: map[string]string{
   171  			"virtlet-foo42/virtlet/kube-system: virtlet --diag": string(fakeDiagResults[0].ToJSON()),
   172  			"virtlet-bar42/virtlet/kube-system: virtlet --diag": string(fakeDiagResults[1].ToJSON()),
   173  		},
   174  	}
   175  	in := bytes.NewBuffer([]byte(input))
   176  	var out bytes.Buffer
   177  	cmd := NewDiagCommand(c, in, &out)
   178  	cmd.SetArgs(args)
   179  	cmd.SilenceUsage = true
   180  	cmd.SilenceErrors = true
   181  	if err := cmd.Execute(); err != nil {
   182  		t.Fatalf("diag: %v", err)
   183  	}
   184  	return out.Bytes()
   185  }
   186  
   187  func TestDiagDumpJSON(t *testing.T) {
   188  	data := runDiagDumpCommand(t, "", "dump", "--json")
   189  	dr, err := diag.DecodeDiagnostics(data)
   190  	if err != nil {
   191  		t.Fatalf("DecodeDiagnostics: %v", err)
   192  	}
   193  
   194  	if !reflect.DeepEqual(expectedDiagResult, dr) {
   195  		t.Errorf("bad diag result. Expected:\n%s\n--- got ---\n%s", expectedDiagResult.ToJSON(), dr.ToJSON())
   196  	}
   197  }
   198  
   199  func verifyDiagFiles(t *testing.T, input, cmd string) {
   200  	tmpDir, err := ioutil.TempDir("", "diag-dump-test")
   201  	if err != nil {
   202  		t.Fatalf("ioutil.TempDir(): %v", err)
   203  	}
   204  	defer os.RemoveAll(tmpDir)
   205  	runDiagDumpCommand(t, input, cmd, tmpDir)
   206  	files, err := testutils.DirToMap(tmpDir)
   207  	if err != nil {
   208  		t.Fatalf("DirToMap(): %v", err)
   209  	}
   210  	if !reflect.DeepEqual(expectedDiagFiles, files) {
   211  		t.Errorf("Bad dir structure. Expected:\n%s--- got ---\n%s", spew.Sdump(expectedDiagFiles), spew.Sdump(files))
   212  	}
   213  }
   214  
   215  func TestDiagDump(t *testing.T) {
   216  	verifyDiagFiles(t, "", "dump")
   217  }
   218  
   219  func TestDiagUnpack(t *testing.T) {
   220  	verifyDiagFiles(t, string(expectedDiagResult.ToJSON()), "unpack")
   221  }
   222  
   223  func TestDiagSonobuoy(t *testing.T) {
   224  	for _, tc := range []struct {
   225  		name string
   226  		args string
   227  	}{
   228  		{
   229  			name: "plain",
   230  			args: "sonobuoy",
   231  		},
   232  		{
   233  			name: "tag",
   234  			args: "sonobuoy --tag 1.1.2",
   235  		},
   236  	} {
   237  		t.Run(tc.name, func(t *testing.T) {
   238  			in := bytes.NewBuffer([]byte(fakeSonobuoyYaml))
   239  			var out bytes.Buffer
   240  			cmd := NewDiagCommand(nil, in, &out)
   241  			cmd.SetArgs(strings.Split(tc.args, " "))
   242  			cmd.SilenceUsage = true
   243  			cmd.SilenceErrors = true
   244  			if err := cmd.Execute(); err != nil {
   245  				t.Fatalf("diag dump: %v", err)
   246  			}
   247  			gm.Verify(t, gm.NewYamlVerifier(out.Bytes()))
   248  		})
   249  	}
   250  }