package godo

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestKubernetesClusters_ListClusters(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	wantClusters := []*KubernetesCluster{
		&KubernetesCluster{
			ID:            "8d91899c-0739-4a1a-acc5-deadbeefbb8f",
			Name:          "blablabla",
			RegionSlug:    "nyc1",
			VersionSlug:   "1.10.0-gen0",
			ClusterSubnet: "10.244.0.0/16",
			ServiceSubnet: "10.245.0.0/16",
			IPv4:          "",
			Tags:          []string(nil),
			VPCUUID:       "880b7f98-f062-404d-b33c-458d545696f6",
			Status: &KubernetesClusterStatus{
				State: KubernetesClusterStatusRunning,
			},
			NodePools: []*KubernetesNodePool{
				{
					ID:    "1a17a012-cb31-4886-a787-deadbeef1191",
					Name:  "blablabla-1",
					Size:  "s-1vcpu-2gb",
					Count: 2,
					Nodes: []*KubernetesNode{
						{
							ID:        "",
							Name:      "",
							Status:    &KubernetesNodeStatus{},
							DropletID: "droplet-1",
							CreatedAt: time.Date(2018, 6, 21, 8, 44, 38, 0, time.UTC),
							UpdatedAt: time.Date(2018, 6, 21, 8, 44, 38, 0, time.UTC),
						},
						{
							ID:        "",
							Name:      "",
							Status:    &KubernetesNodeStatus{},
							DropletID: "droplet-2",
							CreatedAt: time.Date(2018, 6, 21, 8, 44, 38, 0, time.UTC),
							UpdatedAt: time.Date(2018, 6, 21, 8, 44, 38, 0, time.UTC),
						},
					},
				},
			},
			CreatedAt: time.Date(2018, 6, 21, 8, 44, 38, 0, time.UTC),
			UpdatedAt: time.Date(2018, 6, 21, 8, 44, 38, 0, time.UTC),
		},
		&KubernetesCluster{
			ID:            "deadbeef-dead-4aa5-beef-deadbeef347d",
			Name:          "antoine",
			RegionSlug:    "nyc1",
			VersionSlug:   "1.10.0-gen0",
			ClusterSubnet: "10.244.0.0/16",
			ServiceSubnet: "10.245.0.0/16",
			IPv4:          "1.2.3.4",
			VPCUUID:       "880b7f98-f062-404d-b33c-458d545696f7",
			Status: &KubernetesClusterStatus{
				State: KubernetesClusterStatusRunning,
			},
			NodePools: []*KubernetesNodePool{
				{
					ID:    "deadbeef-dead-beef-dead-deadbeefb4b3",
					Name:  "antoine-1",
					Size:  "s-1vcpu-2gb",
					Count: 5,
					Labels: map[string]string{
						"foo": "bar",
					},
					Nodes: []*KubernetesNode{
						{
							ID:        "deadbeef-dead-beef-dead-deadbeefb4b1",
							Name:      "worker-393",
							Status:    &KubernetesNodeStatus{State: "running"},
							DropletID: "droplet-3",
							CreatedAt: time.Date(2018, 6, 15, 7, 10, 23, 0, time.UTC),
							UpdatedAt: time.Date(2018, 6, 15, 7, 11, 26, 0, time.UTC),
						},
						{
							ID:        "deadbeef-dead-beef-dead-deadbeefb4b2",
							Name:      "worker-394",
							Status:    &KubernetesNodeStatus{State: "running"},
							DropletID: "droplet-4",
							CreatedAt: time.Date(2018, 6, 15, 7, 10, 23, 0, time.UTC),
							UpdatedAt: time.Date(2018, 6, 15, 7, 11, 26, 0, time.UTC),
						},
					},
				},
			},
			CreatedAt: time.Date(2018, 6, 15, 7, 10, 23, 0, time.UTC),
			UpdatedAt: time.Date(2018, 6, 15, 7, 11, 26, 0, time.UTC),
		},
	}
	jBlob := `
{
	"kubernetes_clusters": [
		{
			"id": "8d91899c-0739-4a1a-acc5-deadbeefbb8f",
			"name": "blablabla",
			"region": "nyc1",
			"version": "1.10.0-gen0",
			"cluster_subnet": "10.244.0.0/16",
			"service_subnet": "10.245.0.0/16",
			"ipv4": "",
			"tags": null,
			"vpc_uuid": "880b7f98-f062-404d-b33c-458d545696f6",
			"status": {
				"state": "running"
			},
			"node_pools": [
				{
					"id": "1a17a012-cb31-4886-a787-deadbeef1191",
					"name": "blablabla-1",
					"version": "1.10.0-gen0",
					"size": "s-1vcpu-2gb",
					"count": 2,
					"tags": null,
					"labels": null,
					"nodes": [
						{
							"id": "",
							"name": "",
							"status": {
								"state": ""
							},
							"droplet_id": "droplet-1",
							"created_at": "2018-06-21T08:44:38Z",
							"updated_at": "2018-06-21T08:44:38Z"
						},
						{
							"id": "",
							"name": "",
							"status": {
								"state": ""
							},
							"droplet_id": "droplet-2",
							"created_at": "2018-06-21T08:44:38Z",
							"updated_at": "2018-06-21T08:44:38Z"
						}
					]
				}
			],
			"created_at": "2018-06-21T08:44:38Z",
			"updated_at": "2018-06-21T08:44:38Z"
		},
		{
			"id": "deadbeef-dead-4aa5-beef-deadbeef347d",
			"name": "antoine",
			"region": "nyc1",
			"version": "1.10.0-gen0",
			"cluster_subnet": "10.244.0.0/16",
			"service_subnet": "10.245.0.0/16",
			"ipv4": "1.2.3.4",
			"tags": null,
			"status": {
				"state": "running"
			},
			"vpc_uuid": "880b7f98-f062-404d-b33c-458d545696f7",
			"node_pools": [
				{
					"id": "deadbeef-dead-beef-dead-deadbeefb4b3",
					"name": "antoine-1",
					"version": "1.10.0-gen0",
					"size": "s-1vcpu-2gb",
					"count": 5,
					"tags": null,
					"labels": {
						"foo": "bar"
					},
					"nodes": [
						{
							"id": "deadbeef-dead-beef-dead-deadbeefb4b1",
							"name": "worker-393",
							"status": {
								"state": "running"
							},
							"droplet_id": "droplet-3",
							"created_at": "2018-06-15T07:10:23Z",
							"updated_at": "2018-06-15T07:11:26Z"
						},
						{
							"id": "deadbeef-dead-beef-dead-deadbeefb4b2",
							"name": "worker-394",
							"status": {
								"state": "running"
							},
							"droplet_id": "droplet-4",
							"created_at": "2018-06-15T07:10:23Z",
							"updated_at": "2018-06-15T07:11:26Z"
						}
					]
				}
			],
			"created_at": "2018-06-15T07:10:23Z",
			"updated_at": "2018-06-15T07:11:26Z"
		}
	],
	"links": {
	    "pages": {
			"next": "https://api.digitalocean.com/v2/kubernetes/clusters?page=2",
			"last": "https://api.digitalocean.com/v2/kubernetes/clusters?page=2"
		}
	},
	"meta": {
	    "total": 2
	}
}`

	mux.HandleFunc("/v2/kubernetes/clusters", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodGet)
		fmt.Fprint(w, jBlob)
	})

	gotClusters, resp, err := kubeSvc.List(ctx, nil)
	require.NoError(t, err)
	assert.Equal(t, wantClusters, gotClusters)

	gotRespLinks := resp.Links
	wantRespLinks := &Links{
		Pages: &Pages{
			Next: "https://api.digitalocean.com/v2/kubernetes/clusters?page=2",
			Last: "https://api.digitalocean.com/v2/kubernetes/clusters?page=2",
		},
	}
	assert.Equal(t, wantRespLinks, gotRespLinks)

	gotRespMeta := resp.Meta
	wantRespMeta := &Meta{
		Total: 2,
	}
	assert.Equal(t, wantRespMeta, gotRespMeta)
}

func TestKubernetesClusters_Get(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes
	want := &KubernetesCluster{
		ID:            "deadbeef-dead-4aa5-beef-deadbeef347d",
		Name:          "antoine",
		RegionSlug:    "nyc1",
		VersionSlug:   "1.10.0-gen0",
		ClusterSubnet: "10.244.0.0/16",
		ServiceSubnet: "10.245.0.0/16",
		IPv4:          "1.2.3.4",
		VPCUUID:       "880b7f98-f062-404d-b33c-458d545696f6",
		Status: &KubernetesClusterStatus{
			State: KubernetesClusterStatusRunning,
		},
		NodePools: []*KubernetesNodePool{
			{
				ID:    "deadbeef-dead-beef-dead-deadbeefb4b3",
				Name:  "antoine-1",
				Size:  "s-1vcpu-2gb",
				Count: 5,
				Labels: map[string]string{
					"foo": "bar",
				},
				Nodes: []*KubernetesNode{
					{
						ID:        "deadbeef-dead-beef-dead-deadbeefb4b1",
						Name:      "worker-393",
						Status:    &KubernetesNodeStatus{State: "running"},
						DropletID: "droplet-1",
						CreatedAt: time.Date(2018, 6, 15, 7, 10, 23, 0, time.UTC),
						UpdatedAt: time.Date(2018, 6, 15, 7, 11, 26, 0, time.UTC),
					},
					{
						ID:        "deadbeef-dead-beef-dead-deadbeefb4b2",
						Name:      "worker-394",
						Status:    &KubernetesNodeStatus{State: "running"},
						DropletID: "droplet-2",
						CreatedAt: time.Date(2018, 6, 15, 7, 10, 23, 0, time.UTC),
						UpdatedAt: time.Date(2018, 6, 15, 7, 11, 26, 0, time.UTC),
					},
				},
			},
		},
		MaintenancePolicy: &KubernetesMaintenancePolicy{
			StartTime: "00:00",
			Day:       KubernetesMaintenanceDayMonday,
		},
		CreatedAt: time.Date(2018, 6, 15, 7, 10, 23, 0, time.UTC),
		UpdatedAt: time.Date(2018, 6, 15, 7, 11, 26, 0, time.UTC),
	}
	jBlob := `
{
	"kubernetes_cluster": {
		"id": "deadbeef-dead-4aa5-beef-deadbeef347d",
		"name": "antoine",
		"region": "nyc1",
		"version": "1.10.0-gen0",
		"cluster_subnet": "10.244.0.0/16",
		"service_subnet": "10.245.0.0/16",
		"ipv4": "1.2.3.4",
		"tags": null,
		"vpc_uuid": "880b7f98-f062-404d-b33c-458d545696f6",
		"status": {
			"state": "running"
		},
		"node_pools": [
			{
				"id": "deadbeef-dead-beef-dead-deadbeefb4b3",
				"name": "antoine-1",
				"version": "1.10.0-gen0",
				"size": "s-1vcpu-2gb",
				"count": 5,
				"tags": null,
				"labels": {
					"foo": "bar"
				},
				"nodes": [
					{
						"id": "deadbeef-dead-beef-dead-deadbeefb4b1",
						"name": "worker-393",
						"status": {
							"state": "running"
						},
						"droplet_id": "droplet-1",
						"created_at": "2018-06-15T07:10:23Z",
						"updated_at": "2018-06-15T07:11:26Z"
					},
					{
						"id": "deadbeef-dead-beef-dead-deadbeefb4b2",
						"name": "worker-394",
						"status": {
							"state": "running"
						},
						"droplet_id": "droplet-2",
						"created_at": "2018-06-15T07:10:23Z",
						"updated_at": "2018-06-15T07:11:26Z"
					}
				]
			}
		],
		"maintenance_policy": {
			"start_time": "00:00",
			"day": "monday"
		},
		"created_at": "2018-06-15T07:10:23Z",
		"updated_at": "2018-06-15T07:11:26Z"
	}
}`

	mux.HandleFunc("/v2/kubernetes/clusters/deadbeef-dead-4aa5-beef-deadbeef347d", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodGet)
		fmt.Fprint(w, jBlob)
	})
	got, _, err := kubeSvc.Get(ctx, "deadbeef-dead-4aa5-beef-deadbeef347d")
	require.NoError(t, err)
	require.Equal(t, want, got)
}

func TestKubernetesClusters_GetUser(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes
	want := &KubernetesClusterUser{
		Username: "foo@example.com",
		Groups: []string{
			"foo:bar",
		},
	}
	jBlob := `
{
	"kubernetes_cluster_user": {
		"username": "foo@example.com",
		"groups": ["foo:bar"]
	}
}`

	mux.HandleFunc("/v2/kubernetes/clusters/deadbeef-dead-4aa5-beef-deadbeef347d/user", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodGet)
		fmt.Fprint(w, jBlob)
	})
	got, _, err := kubeSvc.GetUser(ctx, "deadbeef-dead-4aa5-beef-deadbeef347d")
	require.NoError(t, err)
	require.Equal(t, want, got)
}

func TestKubernetesClusters_GetKubeConfig(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes
	want := "some YAML"
	blob := []byte(want)
	mux.HandleFunc("/v2/kubernetes/clusters/deadbeef-dead-4aa5-beef-deadbeef347d/kubeconfig", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodGet)
		fmt.Fprint(w, want)
	})
	got, _, err := kubeSvc.GetKubeConfig(ctx, "deadbeef-dead-4aa5-beef-deadbeef347d")
	require.NoError(t, err)
	require.Equal(t, blob, got.KubeconfigYAML)
}

func TestKubernetesClusters_GetCredentials(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes
	timestamp, err := time.Parse(time.RFC3339, "2014-11-12T11:45:26.371Z")
	require.NoError(t, err)
	want := &KubernetesClusterCredentials{
		Token:     "secret",
		ExpiresAt: timestamp,
	}
	jBlob := `
{
	"token": "secret",
	"expires_at": "2014-11-12T11:45:26.371Z"
}`
	mux.HandleFunc("/v2/kubernetes/clusters/deadbeef-dead-4aa5-beef-deadbeef347d/credentials", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodGet)
		assert.Empty(t, r.URL.Query())
		fmt.Fprint(w, jBlob)
	})
	got, _, err := kubeSvc.GetCredentials(ctx, "deadbeef-dead-4aa5-beef-deadbeef347d", &KubernetesClusterCredentialsGetRequest{})
	require.NoError(t, err)
	require.Equal(t, want, got)
}

func TestKubernetesClusters_GetCredentials_WithExpirySeconds(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes
	timestamp, err := time.Parse(time.RFC3339, "2014-11-12T11:45:26.371Z")
	require.NoError(t, err)
	want := &KubernetesClusterCredentials{
		Token:     "secret",
		ExpiresAt: timestamp,
	}
	jBlob := `
{
	"token": "secret",
	"expires_at": "2014-11-12T11:45:26.371Z"
}`
	mux.HandleFunc("/v2/kubernetes/clusters/deadbeef-dead-4aa5-beef-deadbeef347d/credentials", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodGet)
		expirySeconds, ok := r.URL.Query()["expiry_seconds"]
		assert.True(t, ok)
		assert.Len(t, expirySeconds, 1)
		assert.Contains(t, expirySeconds, "3600")
		fmt.Fprint(w, jBlob)
	})
	got, _, err := kubeSvc.GetCredentials(ctx, "deadbeef-dead-4aa5-beef-deadbeef347d", &KubernetesClusterCredentialsGetRequest{
		ExpirySeconds: intPtr(60 * 60),
	})
	require.NoError(t, err)
	require.Equal(t, want, got)
}

func TestKubernetesClusters_GetUpgrades(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes
	want := []*KubernetesVersion{
		{
			Slug:              "1.12.3-do.2",
			KubernetesVersion: "1.12.3",
		},
		{
			Slug:              "1.13.1-do.1",
			KubernetesVersion: "1.13.1",
		},
	}
	jBlob := `
{
	"available_upgrade_versions": [
		{
			"slug": "1.12.3-do.2",
			"kubernetes_version": "1.12.3"
		},
		{
			"slug": "1.13.1-do.1",
			"kubernetes_version": "1.13.1"
		}
	]
}
`

	mux.HandleFunc("/v2/kubernetes/clusters/deadbeef-dead-4aa5-beef-deadbeef347d/upgrades", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodGet)
		fmt.Fprint(w, jBlob)
	})
	got, _, err := kubeSvc.GetUpgrades(ctx, "deadbeef-dead-4aa5-beef-deadbeef347d")
	require.NoError(t, err)
	require.Equal(t, want, got)
}

func TestKubernetesClusters_Create(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	want := &KubernetesCluster{
		ID:            "8d91899c-0739-4a1a-acc5-deadbeefbb8f",
		Name:          "antoine-test-cluster",
		RegionSlug:    "s2r1",
		VersionSlug:   "1.10.0-gen0",
		ClusterSubnet: "10.244.0.0/16",
		ServiceSubnet: "10.245.0.0/16",
		Tags:          []string{"cluster-tag-1", "cluster-tag-2"},
		VPCUUID:       "880b7f98-f062-404d-b33c-458d545696f6",
		NodePools: []*KubernetesNodePool{
			&KubernetesNodePool{
				ID:     "8d91899c-0739-4a1a-acc5-deadbeefbb8a",
				Size:   "s-1vcpu-1gb",
				Count:  2,
				Name:   "pool-a",
				Tags:   []string{"tag-1"},
				Labels: map[string]string{"foo": "bar"},
			},
		},
		MaintenancePolicy: &KubernetesMaintenancePolicy{
			StartTime: "00:00",
			Day:       KubernetesMaintenanceDayMonday,
		},
	}
	createRequest := &KubernetesClusterCreateRequest{
		Name:        want.Name,
		RegionSlug:  want.RegionSlug,
		VersionSlug: want.VersionSlug,
		Tags:        want.Tags,
		VPCUUID:     want.VPCUUID,
		NodePools: []*KubernetesNodePoolCreateRequest{
			&KubernetesNodePoolCreateRequest{
				Size:      want.NodePools[0].Size,
				Count:     want.NodePools[0].Count,
				Name:      want.NodePools[0].Name,
				Tags:      want.NodePools[0].Tags,
				Labels:    want.NodePools[0].Labels,
				AutoScale: want.NodePools[0].AutoScale,
				MinNodes:  want.NodePools[0].MinNodes,
				MaxNodes:  want.NodePools[0].MaxNodes,
			},
		},
		MaintenancePolicy: want.MaintenancePolicy,
	}

	jBlob := `
{
	"kubernetes_cluster": {
		"id": "8d91899c-0739-4a1a-acc5-deadbeefbb8f",
		"name": "antoine-test-cluster",
		"region": "s2r1",
		"version": "1.10.0-gen0",
		"cluster_subnet": "10.244.0.0/16",
		"service_subnet": "10.245.0.0/16",
		"tags": [
			"cluster-tag-1",
			"cluster-tag-2"
		],
		"vpc_uuid": "880b7f98-f062-404d-b33c-458d545696f6",
		"node_pools": [
			{
				"id": "8d91899c-0739-4a1a-acc5-deadbeefbb8a",
				"size": "s-1vcpu-1gb",
				"count": 2,
				"name": "pool-a",
				"tags": [
					"tag-1"
				],
				"labels": {
					"foo": "bar"
				}
			}
		],
		"maintenance_policy": {
			"start_time": "00:00",
			"day": "monday"
		}
	}
}`

	mux.HandleFunc("/v2/kubernetes/clusters", func(w http.ResponseWriter, r *http.Request) {
		v := new(KubernetesClusterCreateRequest)
		err := json.NewDecoder(r.Body).Decode(v)
		if err != nil {
			t.Fatal(err)
		}

		testMethod(t, r, http.MethodPost)
		require.Equal(t, v, createRequest)
		fmt.Fprint(w, jBlob)
	})

	got, _, err := kubeSvc.Create(ctx, createRequest)
	require.NoError(t, err)
	require.Equal(t, want, got)
}

func TestKubernetesClusters_Create_AutoScalePool(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	want := &KubernetesCluster{
		ID:            "8d91899c-0739-4a1a-acc5-deadbeefbb8f",
		Name:          "antoine-test-cluster",
		RegionSlug:    "s2r1",
		VersionSlug:   "1.10.0-gen0",
		ClusterSubnet: "10.244.0.0/16",
		ServiceSubnet: "10.245.0.0/16",
		Tags:          []string{"cluster-tag-1", "cluster-tag-2"},
		VPCUUID:       "880b7f98-f062-404d-b33c-458d545696f6",
		NodePools: []*KubernetesNodePool{
			&KubernetesNodePool{
				ID:        "8d91899c-0739-4a1a-acc5-deadbeefbb8a",
				Size:      "s-1vcpu-1gb",
				Count:     2,
				Name:      "pool-a",
				Tags:      []string{"tag-1"},
				AutoScale: true,
				MinNodes:  0,
				MaxNodes:  10,
			},
		},
		MaintenancePolicy: &KubernetesMaintenancePolicy{
			StartTime: "00:00",
			Day:       KubernetesMaintenanceDayMonday,
		},
	}
	createRequest := &KubernetesClusterCreateRequest{
		Name:        want.Name,
		RegionSlug:  want.RegionSlug,
		VersionSlug: want.VersionSlug,
		Tags:        want.Tags,
		VPCUUID:     want.VPCUUID,
		NodePools: []*KubernetesNodePoolCreateRequest{
			&KubernetesNodePoolCreateRequest{
				Size:      want.NodePools[0].Size,
				Count:     want.NodePools[0].Count,
				Name:      want.NodePools[0].Name,
				Tags:      want.NodePools[0].Tags,
				AutoScale: want.NodePools[0].AutoScale,
				MinNodes:  want.NodePools[0].MinNodes,
				MaxNodes:  want.NodePools[0].MaxNodes,
			},
		},
		MaintenancePolicy: want.MaintenancePolicy,
	}

	jBlob := `
{
	"kubernetes_cluster": {
		"id": "8d91899c-0739-4a1a-acc5-deadbeefbb8f",
		"name": "antoine-test-cluster",
		"region": "s2r1",
		"version": "1.10.0-gen0",
		"cluster_subnet": "10.244.0.0/16",
		"service_subnet": "10.245.0.0/16",
		"tags": [
			"cluster-tag-1",
			"cluster-tag-2"
		],
		"vpc_uuid": "880b7f98-f062-404d-b33c-458d545696f6",
		"node_pools": [
			{
				"id": "8d91899c-0739-4a1a-acc5-deadbeefbb8a",
				"size": "s-1vcpu-1gb",
				"count": 2,
				"name": "pool-a",
				"tags": [
					"tag-1"
				],
				"auto_scale": true,
				"min_nodes": 0,
				"max_nodes": 10
			}
		],
		"maintenance_policy": {
			"start_time": "00:00",
			"day": "monday"
		}
	}
}`

	mux.HandleFunc("/v2/kubernetes/clusters", func(w http.ResponseWriter, r *http.Request) {
		v := new(KubernetesClusterCreateRequest)
		err := json.NewDecoder(r.Body).Decode(v)
		if err != nil {
			t.Fatal(err)
		}

		testMethod(t, r, http.MethodPost)
		require.Equal(t, v, createRequest)
		fmt.Fprint(w, jBlob)
	})

	got, _, err := kubeSvc.Create(ctx, createRequest)
	require.NoError(t, err)
	require.Equal(t, want, got)
}

func TestKubernetesClusters_Update(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	want := &KubernetesCluster{
		ID:            "8d91899c-0739-4a1a-acc5-deadbeefbb8f",
		Name:          "antoine-test-cluster",
		RegionSlug:    "s2r1",
		VersionSlug:   "1.10.0-gen0",
		ClusterSubnet: "10.244.0.0/16",
		ServiceSubnet: "10.245.0.0/16",
		Tags:          []string{"cluster-tag-1", "cluster-tag-2"},
		VPCUUID:       "880b7f98-f062-404d-b33c-458d545696f6",
		NodePools: []*KubernetesNodePool{
			&KubernetesNodePool{
				ID:    "8d91899c-0739-4a1a-acc5-deadbeefbb8a",
				Size:  "s-1vcpu-1gb",
				Count: 2,
				Name:  "pool-a",
				Tags:  []string{"tag-1"},
				Labels: map[string]string{
					"foo": "bar",
				},
			},
		},
		MaintenancePolicy: &KubernetesMaintenancePolicy{
			StartTime: "00:00",
			Day:       KubernetesMaintenanceDayMonday,
		},
	}
	updateRequest := &KubernetesClusterUpdateRequest{
		Name:              want.Name,
		Tags:              want.Tags,
		MaintenancePolicy: want.MaintenancePolicy,
	}

	jBlob := `
{
	"kubernetes_cluster": {
		"id": "8d91899c-0739-4a1a-acc5-deadbeefbb8f",
		"name": "antoine-test-cluster",
		"region": "s2r1",
		"version": "1.10.0-gen0",
		"cluster_subnet": "10.244.0.0/16",
		"service_subnet": "10.245.0.0/16",
		"tags": [
			"cluster-tag-1",
			"cluster-tag-2"
		],
		"vpc_uuid": "880b7f98-f062-404d-b33c-458d545696f6",
		"node_pools": [
			{
				"id": "8d91899c-0739-4a1a-acc5-deadbeefbb8a",
				"size": "s-1vcpu-1gb",
				"count": 2,
				"name": "pool-a",
				"tags": [
					"tag-1"
				],
				"labels": {
					"foo": "bar"
				}
			}
		],
		"maintenance_policy": {
			"start_time": "00:00",
			"day": "monday"
		}
	}
}`

	expectedReqJSON := `{"name":"antoine-test-cluster","tags":["cluster-tag-1","cluster-tag-2"],"maintenance_policy":{"start_time":"00:00","duration":"","day":"monday"}}
`

	mux.HandleFunc("/v2/kubernetes/clusters/8d91899c-0739-4a1a-acc5-deadbeefbb8f", func(w http.ResponseWriter, r *http.Request) {
		buf := new(bytes.Buffer)
		buf.ReadFrom(r.Body)
		require.Equal(t, expectedReqJSON, buf.String())

		v := new(KubernetesClusterUpdateRequest)
		err := json.NewDecoder(buf).Decode(v)
		require.NoError(t, err)

		testMethod(t, r, http.MethodPut)
		require.Equal(t, v, updateRequest)
		fmt.Fprint(w, jBlob)
	})

	got, _, err := kubeSvc.Update(ctx, "8d91899c-0739-4a1a-acc5-deadbeefbb8f", updateRequest)
	require.NoError(t, err)
	require.Equal(t, want, got)
}

func TestKubernetesClusters_Update_FalseAutoUpgrade(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	want := &KubernetesCluster{
		ID:            "8d91899c-0739-4a1a-acc5-deadbeefbb8f",
		Name:          "antoine-test-cluster",
		RegionSlug:    "s2r1",
		VersionSlug:   "1.10.0-gen0",
		ClusterSubnet: "10.244.0.0/16",
		ServiceSubnet: "10.245.0.0/16",
		Tags:          []string{"cluster-tag-1", "cluster-tag-2"},
		VPCUUID:       "880b7f98-f062-404d-b33c-458d545696f6",
		NodePools: []*KubernetesNodePool{
			&KubernetesNodePool{
				ID:    "8d91899c-0739-4a1a-acc5-deadbeefbb8a",
				Size:  "s-1vcpu-1gb",
				Count: 2,
				Name:  "pool-a",
				Tags:  []string{"tag-1"},
			},
		},
		MaintenancePolicy: &KubernetesMaintenancePolicy{
			StartTime: "00:00",
			Day:       KubernetesMaintenanceDayMonday,
		},
	}
	updateRequest := &KubernetesClusterUpdateRequest{
		AutoUpgrade: boolPtr(false),
	}

	jBlob := `
{
	"kubernetes_cluster": {
		"id": "8d91899c-0739-4a1a-acc5-deadbeefbb8f",
		"name": "antoine-test-cluster",
		"region": "s2r1",
		"version": "1.10.0-gen0",
		"cluster_subnet": "10.244.0.0/16",
		"service_subnet": "10.245.0.0/16",
		"tags": [
			"cluster-tag-1",
			"cluster-tag-2"
		],
		"vpc_uuid": "880b7f98-f062-404d-b33c-458d545696f6",
		"node_pools": [
			{
				"id": "8d91899c-0739-4a1a-acc5-deadbeefbb8a",
				"size": "s-1vcpu-1gb",
				"count": 2,
				"name": "pool-a",
				"tags": [
					"tag-1"
				]
			}
		],
		"maintenance_policy": {
			"start_time": "00:00",
			"day": "monday"
		}
	}
}`

	expectedReqJSON := `{"auto_upgrade":false}
`

	mux.HandleFunc("/v2/kubernetes/clusters/8d91899c-0739-4a1a-acc5-deadbeefbb8f", func(w http.ResponseWriter, r *http.Request) {
		buf := new(bytes.Buffer)
		buf.ReadFrom(r.Body)
		require.Equal(t, expectedReqJSON, buf.String())

		v := new(KubernetesClusterUpdateRequest)
		err := json.NewDecoder(buf).Decode(v)
		require.NoError(t, err)

		testMethod(t, r, http.MethodPut)
		require.Equal(t, v, updateRequest)
		fmt.Fprint(w, jBlob)
	})

	got, _, err := kubeSvc.Update(ctx, "8d91899c-0739-4a1a-acc5-deadbeefbb8f", updateRequest)
	require.NoError(t, err)
	require.Equal(t, want, got)
}

func TestKubernetesClusters_Upgrade(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	upgradeRequest := &KubernetesClusterUpgradeRequest{
		VersionSlug: "1.12.3-do.2",
	}

	mux.HandleFunc("/v2/kubernetes/clusters/8d91899c-0739-4a1a-acc5-deadbeefbb8f/upgrade", func(w http.ResponseWriter, r *http.Request) {
		v := new(KubernetesClusterUpgradeRequest)
		err := json.NewDecoder(r.Body).Decode(v)
		if err != nil {
			t.Fatal(err)
		}

		testMethod(t, r, http.MethodPost)
		require.Equal(t, v, upgradeRequest)
	})

	_, err := kubeSvc.Upgrade(ctx, "8d91899c-0739-4a1a-acc5-deadbeefbb8f", upgradeRequest)
	require.NoError(t, err)
}

func TestKubernetesClusters_Destroy(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	mux.HandleFunc("/v2/kubernetes/clusters/deadbeef-dead-4aa5-beef-deadbeef347d", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodDelete)
	})

	_, err := kubeSvc.Delete(ctx, "deadbeef-dead-4aa5-beef-deadbeef347d")
	require.NoError(t, err)
}

func TestKubernetesClusters_CreateNodePool(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	want := &KubernetesNodePool{
		ID:        "8d91899c-0739-4a1a-acc5-deadbeefbb8a",
		Size:      "s-1vcpu-1gb",
		Count:     2,
		Name:      "pool-a",
		Tags:      []string{"tag-1"},
		Labels:    map[string]string{"foo": "bar"},
		AutoScale: false,
		MinNodes:  0,
		MaxNodes:  0,
	}
	createRequest := &KubernetesNodePoolCreateRequest{
		Size:  want.Size,
		Count: want.Count,
		Name:  want.Name,
		Tags:  want.Tags,
	}

	jBlob := `
{
	"node_pool": {
		"id": "8d91899c-0739-4a1a-acc5-deadbeefbb8a",
		"size": "s-1vcpu-1gb",
		"count": 2,
		"name": "pool-a",
		"tags": [
			"tag-1"
		],
		"labels": {
			"foo": "bar"
		}
	}
}`

	mux.HandleFunc("/v2/kubernetes/clusters/8d91899c-0739-4a1a-acc5-deadbeefbb8f/node_pools", func(w http.ResponseWriter, r *http.Request) {
		v := new(KubernetesNodePoolCreateRequest)
		err := json.NewDecoder(r.Body).Decode(v)
		if err != nil {
			t.Fatal(err)
		}

		testMethod(t, r, http.MethodPost)
		require.Equal(t, v, createRequest)
		fmt.Fprint(w, jBlob)
	})

	got, _, err := kubeSvc.CreateNodePool(ctx, "8d91899c-0739-4a1a-acc5-deadbeefbb8f", createRequest)
	require.NoError(t, err)
	require.Equal(t, want, got)
}

func TestKubernetesClusters_CreateNodePool_AutoScale(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	want := &KubernetesNodePool{
		ID:        "8d91899c-0739-4a1a-acc5-deadbeefbb8a",
		Size:      "s-1vcpu-1gb",
		Count:     2,
		Name:      "pool-a",
		Tags:      []string{"tag-1"},
		AutoScale: true,
		MinNodes:  0,
		MaxNodes:  10,
	}
	createRequest := &KubernetesNodePoolCreateRequest{
		Size:      want.Size,
		Count:     want.Count,
		Name:      want.Name,
		Tags:      want.Tags,
		AutoScale: want.AutoScale,
		MinNodes:  want.MinNodes,
		MaxNodes:  want.MaxNodes,
	}

	jBlob := `
{
	"node_pool": {
		"id": "8d91899c-0739-4a1a-acc5-deadbeefbb8a",
		"size": "s-1vcpu-1gb",
		"count": 2,
		"name": "pool-a",
		"tags": [
			"tag-1"
		],
		"auto_scale": true,
		"min_nodes": 0,
		"max_nodes": 10
	}
}`

	mux.HandleFunc("/v2/kubernetes/clusters/8d91899c-0739-4a1a-acc5-deadbeefbb8f/node_pools", func(w http.ResponseWriter, r *http.Request) {
		v := new(KubernetesNodePoolCreateRequest)
		err := json.NewDecoder(r.Body).Decode(v)
		if err != nil {
			t.Fatal(err)
		}

		testMethod(t, r, http.MethodPost)
		require.Equal(t, v, createRequest)
		fmt.Fprint(w, jBlob)
	})

	got, _, err := kubeSvc.CreateNodePool(ctx, "8d91899c-0739-4a1a-acc5-deadbeefbb8f", createRequest)
	require.NoError(t, err)
	require.Equal(t, want, got)
}

func TestKubernetesClusters_GetNodePool(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	want := &KubernetesNodePool{
		ID:    "8d91899c-0739-4a1a-acc5-deadbeefbb8a",
		Size:  "s-1vcpu-1gb",
		Count: 2,
		Name:  "pool-a",
		Tags:  []string{"tag-1"},
	}

	jBlob := `
{
	"node_pool": {
		"id": "8d91899c-0739-4a1a-acc5-deadbeefbb8a",
		"size": "s-1vcpu-1gb",
		"count": 2,
		"name": "pool-a",
		"tags": [
			"tag-1"
		]
	}
}`

	mux.HandleFunc("/v2/kubernetes/clusters/8d91899c-0739-4a1a-acc5-deadbeefbb8f/node_pools/8d91899c-0739-4a1a-acc5-deadbeefbb8a", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodGet)
		fmt.Fprint(w, jBlob)
	})

	got, _, err := kubeSvc.GetNodePool(ctx, "8d91899c-0739-4a1a-acc5-deadbeefbb8f", "8d91899c-0739-4a1a-acc5-deadbeefbb8a")
	require.NoError(t, err)
	require.Equal(t, want, got)
}

func TestKubernetesClusters_ListNodePools(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	want := []*KubernetesNodePool{
		{
			ID:    "1a17a012-cb31-4886-a787-deadbeef1191",
			Name:  "blablabla-1",
			Size:  "s-1vcpu-2gb",
			Count: 2,
			Nodes: []*KubernetesNode{
				{
					ID:        "",
					Name:      "",
					Status:    &KubernetesNodeStatus{},
					CreatedAt: time.Date(2018, 6, 21, 8, 44, 38, 0, time.UTC),
					UpdatedAt: time.Date(2018, 6, 21, 8, 44, 38, 0, time.UTC),
				},
				{
					ID:        "",
					Name:      "",
					Status:    &KubernetesNodeStatus{},
					CreatedAt: time.Date(2018, 6, 21, 8, 44, 38, 0, time.UTC),
					UpdatedAt: time.Date(2018, 6, 21, 8, 44, 38, 0, time.UTC),
				},
			},
		},
	}
	jBlob := `
{
	"node_pools": [
		{
			"id": "1a17a012-cb31-4886-a787-deadbeef1191",
			"name": "blablabla-1",
			"version": "1.10.0-gen0",
			"size": "s-1vcpu-2gb",
			"count": 2,
			"tags": null,
			"nodes": [
				{
					"id": "",
					"name": "",
					"status": {
						"state": ""
					},
					"created_at": "2018-06-21T08:44:38Z",
					"updated_at": "2018-06-21T08:44:38Z"
				},
				{
					"id": "",
					"name": "",
					"status": {
						"state": ""
					},
					"created_at": "2018-06-21T08:44:38Z",
					"updated_at": "2018-06-21T08:44:38Z"
				}
			]
		}
	]
}`

	mux.HandleFunc("/v2/kubernetes/clusters/8d91899c-0739-4a1a-acc5-deadbeefbb8f/node_pools", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodGet)
		fmt.Fprint(w, jBlob)
	})

	got, _, err := kubeSvc.ListNodePools(ctx, "8d91899c-0739-4a1a-acc5-deadbeefbb8f", nil)
	require.NoError(t, err)
	require.Equal(t, want, got)
}

func TestKubernetesClusters_UpdateNodePool(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	want := &KubernetesNodePool{
		ID:        "8d91899c-nodepool-4a1a-acc5-deadbeefbb8a",
		Name:      "a better name",
		Size:      "s-1vcpu-1gb",
		Count:     4,
		Tags:      []string{"tag-1", "tag-2"},
		Labels:    map[string]string{"foo": "bar"},
		AutoScale: false,
		MinNodes:  0,
		MaxNodes:  0,
	}
	updateRequest := &KubernetesNodePoolUpdateRequest{
		Name:  "a better name",
		Count: intPtr(4),
		Tags:  []string{"tag-1", "tag-2"},
	}

	jBlob := `
{
	"node_pool": {
		"id": "8d91899c-nodepool-4a1a-acc5-deadbeefbb8a",
		"size": "s-1vcpu-1gb",
		"count": 4,
		"name": "a better name",
		"tags": [
			"tag-1", "tag-2"
		],
		"labels": {
			"foo": "bar"
		}
	}
}`

	mux.HandleFunc("/v2/kubernetes/clusters/8d91899c-0739-4a1a-acc5-deadbeefbb8f/node_pools/8d91899c-nodepool-4a1a-acc5-deadbeefbb8a", func(w http.ResponseWriter, r *http.Request) {
		v := new(KubernetesNodePoolUpdateRequest)
		err := json.NewDecoder(r.Body).Decode(v)
		if err != nil {
			t.Fatal(err)
		}

		testMethod(t, r, http.MethodPut)
		require.Equal(t, v, updateRequest)
		fmt.Fprint(w, jBlob)
	})

	got, _, err := kubeSvc.UpdateNodePool(ctx, "8d91899c-0739-4a1a-acc5-deadbeefbb8f", "8d91899c-nodepool-4a1a-acc5-deadbeefbb8a", updateRequest)
	require.NoError(t, err)
	require.Equal(t, want, got)
}

func TestKubernetesClusters_UpdateNodePool_ZeroCount(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	want := &KubernetesNodePool{
		ID:        "8d91899c-nodepool-4a1a-acc5-deadbeefbb8a",
		Name:      "name",
		Size:      "s-1vcpu-1gb",
		Count:     0,
		Tags:      []string{"tag-1", "tag-2"},
		AutoScale: false,
		MinNodes:  0,
		MaxNodes:  0,
	}
	updateRequest := &KubernetesNodePoolUpdateRequest{
		Count: intPtr(0),
	}

	jBlob := `
{
	"node_pool": {
		"id": "8d91899c-nodepool-4a1a-acc5-deadbeefbb8a",
		"size": "s-1vcpu-1gb",
		"count": 0,
		"name": "name",
		"tags": [
			"tag-1", "tag-2"
		]
	}
}`

	expectedReqJSON := `{"count":0}
`

	mux.HandleFunc("/v2/kubernetes/clusters/8d91899c-0739-4a1a-acc5-deadbeefbb8f/node_pools/8d91899c-nodepool-4a1a-acc5-deadbeefbb8a", func(w http.ResponseWriter, r *http.Request) {
		buf := new(bytes.Buffer)
		buf.ReadFrom(r.Body)
		require.Equal(t, expectedReqJSON, buf.String())

		v := new(KubernetesNodePoolUpdateRequest)
		err := json.NewDecoder(buf).Decode(v)
		require.NoError(t, err)

		testMethod(t, r, http.MethodPut)
		require.Equal(t, v, updateRequest)
		fmt.Fprint(w, jBlob)
	})

	got, _, err := kubeSvc.UpdateNodePool(ctx, "8d91899c-0739-4a1a-acc5-deadbeefbb8f", "8d91899c-nodepool-4a1a-acc5-deadbeefbb8a", updateRequest)
	require.NoError(t, err)
	require.Equal(t, want, got)
}

func TestKubernetesClusters_UpdateNodePool_AutoScale(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	want := &KubernetesNodePool{
		ID:        "8d91899c-nodepool-4a1a-acc5-deadbeefbb8a",
		Name:      "name",
		Size:      "s-1vcpu-1gb",
		Count:     4,
		Tags:      []string{"tag-1", "tag-2"},
		AutoScale: true,
		MinNodes:  0,
		MaxNodes:  10,
	}
	updateRequest := &KubernetesNodePoolUpdateRequest{
		AutoScale: boolPtr(true),
		MinNodes:  intPtr(0),
		MaxNodes:  intPtr(10),
	}

	jBlob := `
{
	"node_pool": {
		"id": "8d91899c-nodepool-4a1a-acc5-deadbeefbb8a",
		"size": "s-1vcpu-1gb",
		"count": 4,
		"name": "name",
		"tags": [
			"tag-1", "tag-2"
		],
		"auto_scale": true,
		"min_nodes": 0,
		"max_nodes": 10
	}
}`

	expectedReqJSON := `{"auto_scale":true,"min_nodes":0,"max_nodes":10}
`

	mux.HandleFunc("/v2/kubernetes/clusters/8d91899c-0739-4a1a-acc5-deadbeefbb8f/node_pools/8d91899c-nodepool-4a1a-acc5-deadbeefbb8a", func(w http.ResponseWriter, r *http.Request) {
		buf := new(bytes.Buffer)
		buf.ReadFrom(r.Body)
		require.Equal(t, expectedReqJSON, buf.String())

		v := new(KubernetesNodePoolUpdateRequest)
		err := json.NewDecoder(buf).Decode(v)
		require.NoError(t, err)

		testMethod(t, r, http.MethodPut)
		require.Equal(t, v, updateRequest)
		fmt.Fprint(w, jBlob)
	})

	got, _, err := kubeSvc.UpdateNodePool(ctx, "8d91899c-0739-4a1a-acc5-deadbeefbb8f", "8d91899c-nodepool-4a1a-acc5-deadbeefbb8a", updateRequest)
	require.NoError(t, err)
	require.Equal(t, want, got)
}

func TestKubernetesClusters_DeleteNodePool(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	mux.HandleFunc("/v2/kubernetes/clusters/deadbeef-dead-4aa5-beef-deadbeef347d/node_pools/8d91899c-nodepool-4a1a-acc5-deadbeefbb8a", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodDelete)
	})

	_, err := kubeSvc.DeleteNodePool(ctx, "deadbeef-dead-4aa5-beef-deadbeef347d", "8d91899c-nodepool-4a1a-acc5-deadbeefbb8a")
	require.NoError(t, err)
}

func TestKubernetesClusters_DeleteNode(t *testing.T) {
	t.Run("default", func(t *testing.T) {
		setup()
		defer teardown()
		kubeSvc := client.Kubernetes

		mux.HandleFunc("/v2/kubernetes/clusters/deadbeef-dead-4aa5-beef-deadbeef347d/node_pools/8d91899c-nodepool-4a1a-acc5-deadbeefbb8a/nodes/8d91899c-node-4a1a-acc5-deadbeefbb8a", func(w http.ResponseWriter, r *http.Request) {
			testMethod(t, r, http.MethodDelete)
			require.Equal(t, "", r.URL.Query().Encode())
		})

		_, err := kubeSvc.DeleteNode(ctx, "deadbeef-dead-4aa5-beef-deadbeef347d", "8d91899c-nodepool-4a1a-acc5-deadbeefbb8a", "8d91899c-node-4a1a-acc5-deadbeefbb8a", nil)
		require.NoError(t, err)
	})

	t.Run("drain", func(t *testing.T) {
		setup()
		defer teardown()
		kubeSvc := client.Kubernetes

		mux.HandleFunc("/v2/kubernetes/clusters/deadbeef-dead-4aa5-beef-deadbeef347d/node_pools/8d91899c-nodepool-4a1a-acc5-deadbeefbb8a/nodes/8d91899c-node-4a1a-acc5-deadbeefbb8a", func(w http.ResponseWriter, r *http.Request) {
			testMethod(t, r, http.MethodDelete)
			require.Equal(t, "skip_drain=1", r.URL.Query().Encode())
		})

		_, err := kubeSvc.DeleteNode(ctx, "deadbeef-dead-4aa5-beef-deadbeef347d", "8d91899c-nodepool-4a1a-acc5-deadbeefbb8a", "8d91899c-node-4a1a-acc5-deadbeefbb8a", &KubernetesNodeDeleteRequest{
			SkipDrain: true,
		})
		require.NoError(t, err)
	})

	t.Run("replace", func(t *testing.T) {
		setup()
		defer teardown()
		kubeSvc := client.Kubernetes

		mux.HandleFunc("/v2/kubernetes/clusters/deadbeef-dead-4aa5-beef-deadbeef347d/node_pools/8d91899c-nodepool-4a1a-acc5-deadbeefbb8a/nodes/8d91899c-node-4a1a-acc5-deadbeefbb8a", func(w http.ResponseWriter, r *http.Request) {
			testMethod(t, r, http.MethodDelete)
			require.Equal(t, "replace=1", r.URL.Query().Encode())
		})

		_, err := kubeSvc.DeleteNode(ctx, "deadbeef-dead-4aa5-beef-deadbeef347d", "8d91899c-nodepool-4a1a-acc5-deadbeefbb8a", "8d91899c-node-4a1a-acc5-deadbeefbb8a", &KubernetesNodeDeleteRequest{
			Replace: true,
		})
		require.NoError(t, err)
	})
}

func TestKubernetesClusters_RecycleNodePoolNodes(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	recycleRequest := &KubernetesNodePoolRecycleNodesRequest{
		Nodes: []string{"node1", "node2"},
	}

	mux.HandleFunc("/v2/kubernetes/clusters/8d91899c-0739-4a1a-acc5-deadbeefbb8f/node_pools/8d91899c-nodepool-4a1a-acc5-deadbeefbb8a/recycle", func(w http.ResponseWriter, r *http.Request) {
		v := new(KubernetesNodePoolRecycleNodesRequest)
		err := json.NewDecoder(r.Body).Decode(v)
		if err != nil {
			t.Fatal(err)
		}

		testMethod(t, r, http.MethodPost)
		require.Equal(t, v, recycleRequest)
	})

	_, err := kubeSvc.RecycleNodePoolNodes(ctx, "8d91899c-0739-4a1a-acc5-deadbeefbb8f", "8d91899c-nodepool-4a1a-acc5-deadbeefbb8a", recycleRequest)
	require.NoError(t, err)
}

func TestKubernetesVersions_List(t *testing.T) {
	setup()
	defer teardown()

	kubeSvc := client.Kubernetes

	want := &KubernetesOptions{
		Versions: []*KubernetesVersion{
			{Slug: "1.10.0-gen0", KubernetesVersion: "1.10.0"},
		},
		Regions: []*KubernetesRegion{
			{Name: "New York 3", Slug: "nyc3"},
		},
		Sizes: []*KubernetesNodeSize{
			{Name: "c-8", Slug: "c-8"},
		},
	}
	jBlob := `
{
	"options": {
		"versions": [
			{
				"slug": "1.10.0-gen0",
				"kubernetes_version": "1.10.0"
			}
		],
		"regions": [
			{
				"name": "New York 3",
				"slug": "nyc3"
			}
		],
		"sizes": [
			{
				"name": "c-8",
				"slug": "c-8"
			}
		]
	}
}`

	mux.HandleFunc("/v2/kubernetes/options", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodGet)
		fmt.Fprint(w, jBlob)
	})

	got, _, err := kubeSvc.GetOptions(ctx)
	require.NoError(t, err)
	require.Equal(t, want, got)
}

var maintenancePolicyDayTests = []struct {
	name  string
	json  string
	day   KubernetesMaintenancePolicyDay
	valid bool
}{
	{
		name:  "sunday",
		day:   KubernetesMaintenanceDaySunday,
		json:  `"sunday"`,
		valid: true,
	},

	{
		name:  "any",
		day:   KubernetesMaintenanceDayAny,
		json:  `"any"`,
		valid: true,
	},

	{
		name:  "invalid",
		day:   100, // invalid input
		json:  `"invalid weekday (100)"`,
		valid: false,
	},
}

func TestWeekday_UnmarshalJSON(t *testing.T) {
	for _, ts := range maintenancePolicyDayTests {
		t.Run(ts.name, func(t *testing.T) {
			var got KubernetesMaintenancePolicyDay
			err := json.Unmarshal([]byte(ts.json), &got)
			valid := err == nil
			if valid != ts.valid {
				t.Errorf("valid unmarshal case\n\tgot: %+v\n\twant : %+v", valid, ts.valid)
			}

			if valid && got != ts.day {
				t.Errorf("\ninput: %s\ngot : %+v\nwant  : %+v\n",
					ts.day, got, ts.day)
			}
		})
	}
}

func TestWeekday_MarshalJSON(t *testing.T) {
	for _, ts := range maintenancePolicyDayTests {
		t.Run(ts.name, func(t *testing.T) {
			out, err := json.Marshal(ts.day)
			valid := err == nil
			if valid != ts.valid {
				t.Errorf("valid marshal case\n\tgot: %+v\n\twant : %+v", valid, ts.valid)
			}

			if valid && ts.json != string(out) {
				t.Errorf("\ninput: %s\ngot : %+v\nwant  : %+v\n",
					ts.day, string(out), ts.json)
			}
		})
	}
}
