mirror of
				https://github.com/traefik/traefik.git
				synced 2025-11-04 10:21:15 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			145 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package api
 | 
						|
 | 
						|
import (
 | 
						|
	"archive/tar"
 | 
						|
	"compress/gzip"
 | 
						|
	"errors"
 | 
						|
	"io"
 | 
						|
	"net/http"
 | 
						|
	"net/http/httptest"
 | 
						|
	"testing"
 | 
						|
 | 
						|
	"github.com/stretchr/testify/assert"
 | 
						|
	"github.com/stretchr/testify/require"
 | 
						|
	"github.com/traefik/traefik/v3/pkg/config/dynamic"
 | 
						|
	"github.com/traefik/traefik/v3/pkg/config/runtime"
 | 
						|
	"github.com/traefik/traefik/v3/pkg/config/static"
 | 
						|
)
 | 
						|
 | 
						|
func TestHandler_SupportDump(t *testing.T) {
 | 
						|
	testCases := []struct {
 | 
						|
		desc       string
 | 
						|
		path       string
 | 
						|
		confStatic static.Configuration
 | 
						|
		confDyn    runtime.Configuration
 | 
						|
		validate   func(t *testing.T, files map[string][]byte)
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			desc:       "empty configurations",
 | 
						|
			path:       "/api/support-dump",
 | 
						|
			confStatic: static.Configuration{API: &static.API{}, Global: &static.Global{}},
 | 
						|
			confDyn:    runtime.Configuration{},
 | 
						|
			validate: func(t *testing.T, files map[string][]byte) {
 | 
						|
				t.Helper()
 | 
						|
 | 
						|
				require.Contains(t, files, "static-config.json")
 | 
						|
				require.Contains(t, files, "runtime-config.json")
 | 
						|
				require.Contains(t, files, "version.json")
 | 
						|
 | 
						|
				// Verify version.json contains version information
 | 
						|
				assert.Contains(t, string(files["version.json"]), `"version":"dev"`)
 | 
						|
 | 
						|
				assert.JSONEq(t, `{"global":{},"api":{}}`, string(files["static-config.json"]))
 | 
						|
				assert.Equal(t, `{}`, string(files["runtime-config.json"]))
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			desc: "with configuration data",
 | 
						|
			path: "/api/support-dump",
 | 
						|
			confStatic: static.Configuration{
 | 
						|
				API:    &static.API{},
 | 
						|
				Global: &static.Global{},
 | 
						|
				EntryPoints: map[string]*static.EntryPoint{
 | 
						|
					"web": {Address: ":80"},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			confDyn: runtime.Configuration{
 | 
						|
				Services: map[string]*runtime.ServiceInfo{
 | 
						|
					"test-service": {
 | 
						|
						Service: &dynamic.Service{
 | 
						|
							LoadBalancer: &dynamic.ServersLoadBalancer{
 | 
						|
								Servers: []dynamic.Server{{URL: "http://127.0.0.1:8080"}},
 | 
						|
							},
 | 
						|
						},
 | 
						|
						Status: runtime.StatusEnabled,
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			validate: func(t *testing.T, files map[string][]byte) {
 | 
						|
				t.Helper()
 | 
						|
 | 
						|
				require.Contains(t, files, "static-config.json")
 | 
						|
				require.Contains(t, files, "runtime-config.json")
 | 
						|
				require.Contains(t, files, "version.json")
 | 
						|
 | 
						|
				// Verify version.json contains version information
 | 
						|
				assert.Contains(t, string(files["version.json"]), `"version":"dev"`)
 | 
						|
 | 
						|
				// Verify static config contains entry points
 | 
						|
				assert.Contains(t, string(files["static-config.json"]), `"entryPoints":{"web":{"address":"xxxx","http":{}}}`)
 | 
						|
 | 
						|
				// Verify runtime config contains services
 | 
						|
				assert.Contains(t, string(files["runtime-config.json"]), `"services":`)
 | 
						|
				assert.Contains(t, string(files["runtime-config.json"]), `"test-service"`)
 | 
						|
			},
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, test := range testCases {
 | 
						|
		t.Run(test.desc, func(t *testing.T) {
 | 
						|
			t.Parallel()
 | 
						|
 | 
						|
			handler := New(test.confStatic, &test.confDyn)
 | 
						|
			server := httptest.NewServer(handler.createRouter())
 | 
						|
 | 
						|
			resp, err := http.DefaultClient.Get(server.URL + test.path)
 | 
						|
			require.NoError(t, err)
 | 
						|
 | 
						|
			assert.Equal(t, http.StatusOK, resp.StatusCode)
 | 
						|
			assert.Equal(t, "application/gzip", resp.Header.Get("Content-Type"))
 | 
						|
			assert.Equal(t, `attachment; filename=support-dump.tar.gz`, resp.Header.Get("Content-Disposition"))
 | 
						|
 | 
						|
			// Extract and validate the tar.gz contents.
 | 
						|
			files, err := extractTarGz(resp.Body)
 | 
						|
			require.NoError(t, err)
 | 
						|
 | 
						|
			test.validate(t, files)
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// extractTarGz reads a tar.gz archive and returns a map of filename to contents
 | 
						|
func extractTarGz(r io.Reader) (map[string][]byte, error) {
 | 
						|
	files := make(map[string][]byte)
 | 
						|
 | 
						|
	gzr, err := gzip.NewReader(r)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	defer gzr.Close()
 | 
						|
 | 
						|
	tr := tar.NewReader(gzr)
 | 
						|
	for {
 | 
						|
		header, err := tr.Next()
 | 
						|
		if errors.Is(err, io.EOF) {
 | 
						|
			break
 | 
						|
		}
 | 
						|
		if err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
 | 
						|
		if header.Typeflag != tar.TypeReg {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		contents, err := io.ReadAll(tr)
 | 
						|
		if err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
 | 
						|
		files[header.Name] = contents
 | 
						|
	}
 | 
						|
 | 
						|
	return files, nil
 | 
						|
}
 |