kube,cmd/{k8s-operator,containerboot},envknob,ipn/store/kubestore,*/depaware.txt: split out kube types (#13417)

Further split kube package into kube/{client,api,types}. This is so that
consumers who only need constants/static types don't have to import
the client and api bits.

Updates#cleanup

Signed-off-by: Irbe Krumina <irbe@tailscale.com>
pull/13418/head
Irbe Krumina 3 months ago committed by GitHub
parent ecd64f6ed9
commit d6dfb7f242
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -15,14 +15,15 @@ import (
"net/netip" "net/netip"
"os" "os"
"tailscale.com/kube" kubeapi "tailscale.com/kube/api"
kubeclient "tailscale.com/kube/client"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
) )
// storeDeviceID writes deviceID to 'device_id' data field of the named // storeDeviceID writes deviceID to 'device_id' data field of the named
// Kubernetes Secret. // Kubernetes Secret.
func storeDeviceID(ctx context.Context, secretName string, deviceID tailcfg.StableNodeID) error { func storeDeviceID(ctx context.Context, secretName string, deviceID tailcfg.StableNodeID) error {
s := &kube.Secret{ s := &kubeapi.Secret{
Data: map[string][]byte{ Data: map[string][]byte{
"device_id": []byte(deviceID), "device_id": []byte(deviceID),
}, },
@ -42,7 +43,7 @@ func storeDeviceEndpoints(ctx context.Context, secretName string, fqdn string, a
return err return err
} }
s := &kube.Secret{ s := &kubeapi.Secret{
Data: map[string][]byte{ Data: map[string][]byte{
"device_fqdn": []byte(fqdn), "device_fqdn": []byte(fqdn),
"device_ips": deviceIPs, "device_ips": deviceIPs,
@ -55,14 +56,14 @@ func storeDeviceEndpoints(ctx context.Context, secretName string, fqdn string, a
// secret. No-op if there is no authkey in the secret. // secret. No-op if there is no authkey in the secret.
func deleteAuthKey(ctx context.Context, secretName string) error { func deleteAuthKey(ctx context.Context, secretName string) error {
// m is a JSON Patch data structure, see https://jsonpatch.com/ or RFC 6902. // m is a JSON Patch data structure, see https://jsonpatch.com/ or RFC 6902.
m := []kube.JSONPatch{ m := []kubeclient.JSONPatch{
{ {
Op: "remove", Op: "remove",
Path: "/data/authkey", Path: "/data/authkey",
}, },
} }
if err := kc.JSONPatchSecret(ctx, secretName, m); err != nil { if err := kc.JSONPatchSecret(ctx, secretName, m); err != nil {
if s, ok := err.(*kube.Status); ok && s.Code == http.StatusUnprocessableEntity { if s, ok := err.(*kubeapi.Status); ok && s.Code == http.StatusUnprocessableEntity {
// This is kubernetes-ese for "the field you asked to // This is kubernetes-ese for "the field you asked to
// delete already doesn't exist", aka no-op. // delete already doesn't exist", aka no-op.
return nil return nil
@ -72,7 +73,7 @@ func deleteAuthKey(ctx context.Context, secretName string) error {
return nil return nil
} }
var kc kube.Client var kc kubeclient.Client
// setupKube is responsible for doing any necessary configuration and checks to // setupKube is responsible for doing any necessary configuration and checks to
// ensure that tailscale state storage and authentication mechanism will work on // ensure that tailscale state storage and authentication mechanism will work on
@ -88,12 +89,12 @@ func (cfg *settings) setupKube(ctx context.Context) error {
cfg.KubernetesCanPatch = canPatch cfg.KubernetesCanPatch = canPatch
s, err := kc.GetSecret(ctx, cfg.KubeSecret) s, err := kc.GetSecret(ctx, cfg.KubeSecret)
if err != nil && kube.IsNotFoundErr(err) && !canCreate { if err != nil && kubeclient.IsNotFoundErr(err) && !canCreate {
return fmt.Errorf("Tailscale state Secret %s does not exist and we don't have permissions to create it. "+ return fmt.Errorf("Tailscale state Secret %s does not exist and we don't have permissions to create it. "+
"If you intend to store tailscale state elsewhere than a Kubernetes Secret, "+ "If you intend to store tailscale state elsewhere than a Kubernetes Secret, "+
"you can explicitly set TS_KUBE_SECRET env var to an empty string. "+ "you can explicitly set TS_KUBE_SECRET env var to an empty string. "+
"Else ensure that RBAC is set up that allows the service account associated with this installation to create Secrets.", cfg.KubeSecret) "Else ensure that RBAC is set up that allows the service account associated with this installation to create Secrets.", cfg.KubeSecret)
} else if err != nil && !kube.IsNotFoundErr(err) { } else if err != nil && !kubeclient.IsNotFoundErr(err) {
return fmt.Errorf("Getting Tailscale state Secret %s: %v", cfg.KubeSecret, err) return fmt.Errorf("Getting Tailscale state Secret %s: %v", cfg.KubeSecret, err)
} }
@ -128,10 +129,10 @@ func initKubeClient(root string) {
if root != "/" { if root != "/" {
// If we are running in a test, we need to set the root path to the fake // If we are running in a test, we need to set the root path to the fake
// service account directory. // service account directory.
kube.SetRootPathForTesting(root) kubeclient.SetRootPathForTesting(root)
} }
var err error var err error
kc, err = kube.New() kc, err = kubeclient.New()
if err != nil { if err != nil {
log.Fatalf("Error creating kube client: %v", err) log.Fatalf("Error creating kube client: %v", err)
} }

@ -11,7 +11,8 @@ import (
"testing" "testing"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"tailscale.com/kube" kubeapi "tailscale.com/kube/api"
kubeclient "tailscale.com/kube/client"
) )
func TestSetupKube(t *testing.T) { func TestSetupKube(t *testing.T) {
@ -20,7 +21,7 @@ func TestSetupKube(t *testing.T) {
cfg *settings cfg *settings
wantErr bool wantErr bool
wantCfg *settings wantCfg *settings
kc kube.Client kc kubeclient.Client
}{ }{
{ {
name: "TS_AUTHKEY set, state Secret exists", name: "TS_AUTHKEY set, state Secret exists",
@ -28,11 +29,11 @@ func TestSetupKube(t *testing.T) {
AuthKey: "foo", AuthKey: "foo",
KubeSecret: "foo", KubeSecret: "foo",
}, },
kc: &kube.FakeClient{ kc: &kubeclient.FakeClient{
CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) { CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) {
return false, false, nil return false, false, nil
}, },
GetSecretImpl: func(context.Context, string) (*kube.Secret, error) { GetSecretImpl: func(context.Context, string) (*kubeapi.Secret, error) {
return nil, nil return nil, nil
}, },
}, },
@ -47,12 +48,12 @@ func TestSetupKube(t *testing.T) {
AuthKey: "foo", AuthKey: "foo",
KubeSecret: "foo", KubeSecret: "foo",
}, },
kc: &kube.FakeClient{ kc: &kubeclient.FakeClient{
CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) { CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) {
return false, true, nil return false, true, nil
}, },
GetSecretImpl: func(context.Context, string) (*kube.Secret, error) { GetSecretImpl: func(context.Context, string) (*kubeapi.Secret, error) {
return nil, &kube.Status{Code: 404} return nil, &kubeapi.Status{Code: 404}
}, },
}, },
wantCfg: &settings{ wantCfg: &settings{
@ -66,12 +67,12 @@ func TestSetupKube(t *testing.T) {
AuthKey: "foo", AuthKey: "foo",
KubeSecret: "foo", KubeSecret: "foo",
}, },
kc: &kube.FakeClient{ kc: &kubeclient.FakeClient{
CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) { CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) {
return false, false, nil return false, false, nil
}, },
GetSecretImpl: func(context.Context, string) (*kube.Secret, error) { GetSecretImpl: func(context.Context, string) (*kubeapi.Secret, error) {
return nil, &kube.Status{Code: 404} return nil, &kubeapi.Status{Code: 404}
}, },
}, },
wantCfg: &settings{ wantCfg: &settings{
@ -86,12 +87,12 @@ func TestSetupKube(t *testing.T) {
AuthKey: "foo", AuthKey: "foo",
KubeSecret: "foo", KubeSecret: "foo",
}, },
kc: &kube.FakeClient{ kc: &kubeclient.FakeClient{
CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) { CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) {
return false, false, nil return false, false, nil
}, },
GetSecretImpl: func(context.Context, string) (*kube.Secret, error) { GetSecretImpl: func(context.Context, string) (*kubeapi.Secret, error) {
return nil, &kube.Status{Code: 403} return nil, &kubeapi.Status{Code: 403}
}, },
}, },
wantCfg: &settings{ wantCfg: &settings{
@ -110,7 +111,7 @@ func TestSetupKube(t *testing.T) {
AuthKey: "foo", AuthKey: "foo",
KubeSecret: "foo", KubeSecret: "foo",
}, },
kc: &kube.FakeClient{ kc: &kubeclient.FakeClient{
CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) { CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) {
return false, false, errors.New("broken") return false, false, errors.New("broken")
}, },
@ -126,12 +127,12 @@ func TestSetupKube(t *testing.T) {
wantCfg: &settings{ wantCfg: &settings{
KubeSecret: "foo", KubeSecret: "foo",
}, },
kc: &kube.FakeClient{ kc: &kubeclient.FakeClient{
CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) { CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) {
return false, true, nil return false, true, nil
}, },
GetSecretImpl: func(context.Context, string) (*kube.Secret, error) { GetSecretImpl: func(context.Context, string) (*kubeapi.Secret, error) {
return nil, &kube.Status{Code: 404} return nil, &kubeapi.Status{Code: 404}
}, },
}, },
}, },
@ -144,12 +145,12 @@ func TestSetupKube(t *testing.T) {
wantCfg: &settings{ wantCfg: &settings{
KubeSecret: "foo", KubeSecret: "foo",
}, },
kc: &kube.FakeClient{ kc: &kubeclient.FakeClient{
CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) { CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) {
return false, false, nil return false, false, nil
}, },
GetSecretImpl: func(context.Context, string) (*kube.Secret, error) { GetSecretImpl: func(context.Context, string) (*kubeapi.Secret, error) {
return &kube.Secret{}, nil return &kubeapi.Secret{}, nil
}, },
}, },
}, },
@ -158,12 +159,12 @@ func TestSetupKube(t *testing.T) {
cfg: &settings{ cfg: &settings{
KubeSecret: "foo", KubeSecret: "foo",
}, },
kc: &kube.FakeClient{ kc: &kubeclient.FakeClient{
CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) { CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) {
return false, false, nil return false, false, nil
}, },
GetSecretImpl: func(context.Context, string) (*kube.Secret, error) { GetSecretImpl: func(context.Context, string) (*kubeapi.Secret, error) {
return &kube.Secret{Data: map[string][]byte{"authkey": []byte("foo")}}, nil return &kubeapi.Secret{Data: map[string][]byte{"authkey": []byte("foo")}}, nil
}, },
}, },
wantCfg: &settings{ wantCfg: &settings{
@ -176,12 +177,12 @@ func TestSetupKube(t *testing.T) {
cfg: &settings{ cfg: &settings{
KubeSecret: "foo", KubeSecret: "foo",
}, },
kc: &kube.FakeClient{ kc: &kubeclient.FakeClient{
CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) { CheckSecretPermissionsImpl: func(context.Context, string) (bool, bool, error) {
return true, false, nil return true, false, nil
}, },
GetSecretImpl: func(context.Context, string) (*kube.Secret, error) { GetSecretImpl: func(context.Context, string) (*kubeapi.Secret, error) {
return &kube.Secret{Data: map[string][]byte{"authkey": []byte("foo")}}, nil return &kubeapi.Secret{Data: map[string][]byte{"authkey": []byte("foo")}}, nil
}, },
}, },
wantCfg: &settings{ wantCfg: &settings{

@ -99,7 +99,7 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa
tailscale.com/hostinfo from tailscale.com/net/netmon+ tailscale.com/hostinfo from tailscale.com/net/netmon+
tailscale.com/ipn from tailscale.com/client/tailscale tailscale.com/ipn from tailscale.com/client/tailscale
tailscale.com/ipn/ipnstate from tailscale.com/client/tailscale+ tailscale.com/ipn/ipnstate from tailscale.com/client/tailscale+
tailscale.com/kube from tailscale.com/envknob tailscale.com/kube/types from tailscale.com/envknob
tailscale.com/metrics from tailscale.com/cmd/derper+ tailscale.com/metrics from tailscale.com/cmd/derper+
tailscale.com/net/dnscache from tailscale.com/derp/derphttp tailscale.com/net/dnscache from tailscale.com/derp/derphttp
tailscale.com/net/ktimeout from tailscale.com/cmd/derper tailscale.com/net/ktimeout from tailscale.com/cmd/derper

@ -26,7 +26,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/reconcile"
tsoperator "tailscale.com/k8s-operator" tsoperator "tailscale.com/k8s-operator"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube" kubetypes "tailscale.com/kube/types"
"tailscale.com/tstime" "tailscale.com/tstime"
"tailscale.com/util/clientmetric" "tailscale.com/util/clientmetric"
"tailscale.com/util/set" "tailscale.com/util/set"
@ -62,11 +62,11 @@ type ConnectorReconciler struct {
var ( var (
// gaugeConnectorResources tracks the overall number of Connectors currently managed by this operator instance. // gaugeConnectorResources tracks the overall number of Connectors currently managed by this operator instance.
gaugeConnectorResources = clientmetric.NewGauge(kube.MetricConnectorResourceCount) gaugeConnectorResources = clientmetric.NewGauge(kubetypes.MetricConnectorResourceCount)
// gaugeConnectorSubnetRouterResources tracks the number of Connectors managed by this operator instance that are subnet routers. // gaugeConnectorSubnetRouterResources tracks the number of Connectors managed by this operator instance that are subnet routers.
gaugeConnectorSubnetRouterResources = clientmetric.NewGauge(kube.MetricConnectorWithSubnetRouterCount) gaugeConnectorSubnetRouterResources = clientmetric.NewGauge(kubetypes.MetricConnectorWithSubnetRouterCount)
// gaugeConnectorExitNodeResources tracks the number of Connectors currently managed by this operator instance that are exit nodes. // gaugeConnectorExitNodeResources tracks the number of Connectors currently managed by this operator instance that are exit nodes.
gaugeConnectorExitNodeResources = clientmetric.NewGauge(kube.MetricConnectorWithExitNodeCount) gaugeConnectorExitNodeResources = clientmetric.NewGauge(kubetypes.MetricConnectorWithExitNodeCount)
) )
func (a *ConnectorReconciler) Reconcile(ctx context.Context, req reconcile.Request) (res reconcile.Result, err error) { func (a *ConnectorReconciler) Reconcile(ctx context.Context, req reconcile.Request) (res reconcile.Result, err error) {

@ -16,7 +16,7 @@ import (
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/client/fake"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube" kubetypes "tailscale.com/kube/types"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/util/mak" "tailscale.com/util/mak"
) )
@ -75,7 +75,7 @@ func TestConnector(t *testing.T) {
hostname: "test-connector", hostname: "test-connector",
isExitNode: true, isExitNode: true,
subnetRoutes: "10.40.0.0/14", subnetRoutes: "10.40.0.0/14",
app: kube.AppConnector, app: kubetypes.AppConnector,
} }
expectEqual(t, fc, expectedSecret(t, fc, opts), nil) expectEqual(t, fc, expectedSecret(t, fc, opts), nil)
expectEqual(t, fc, expectedSTS(t, fc, opts), removeHashAnnotation) expectEqual(t, fc, expectedSTS(t, fc, opts), removeHashAnnotation)
@ -171,7 +171,7 @@ func TestConnector(t *testing.T) {
parentType: "connector", parentType: "connector",
subnetRoutes: "10.40.0.0/14", subnetRoutes: "10.40.0.0/14",
hostname: "test-connector", hostname: "test-connector",
app: kube.AppConnector, app: kubetypes.AppConnector,
} }
expectEqual(t, fc, expectedSecret(t, fc, opts), nil) expectEqual(t, fc, expectedSecret(t, fc, opts), nil)
expectEqual(t, fc, expectedSTS(t, fc, opts), removeHashAnnotation) expectEqual(t, fc, expectedSTS(t, fc, opts), removeHashAnnotation)
@ -257,7 +257,7 @@ func TestConnectorWithProxyClass(t *testing.T) {
hostname: "test-connector", hostname: "test-connector",
isExitNode: true, isExitNode: true,
subnetRoutes: "10.40.0.0/14", subnetRoutes: "10.40.0.0/14",
app: kube.AppConnector, app: kubetypes.AppConnector,
} }
expectEqual(t, fc, expectedSecret(t, fc, opts), nil) expectEqual(t, fc, expectedSecret(t, fc, opts), nil)
expectEqual(t, fc, expectedSTS(t, fc, opts), removeHashAnnotation) expectEqual(t, fc, expectedSTS(t, fc, opts), removeHashAnnotation)

@ -690,7 +690,9 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
tailscale.com/k8s-operator/sessionrecording/spdy from tailscale.com/k8s-operator/sessionrecording tailscale.com/k8s-operator/sessionrecording/spdy from tailscale.com/k8s-operator/sessionrecording
tailscale.com/k8s-operator/sessionrecording/tsrecorder from tailscale.com/k8s-operator/sessionrecording+ tailscale.com/k8s-operator/sessionrecording/tsrecorder from tailscale.com/k8s-operator/sessionrecording+
tailscale.com/k8s-operator/sessionrecording/ws from tailscale.com/k8s-operator/sessionrecording tailscale.com/k8s-operator/sessionrecording/ws from tailscale.com/k8s-operator/sessionrecording
tailscale.com/kube from tailscale.com/cmd/k8s-operator+ tailscale.com/kube/api from tailscale.com/ipn/store/kubestore+
tailscale.com/kube/client from tailscale.com/ipn/store/kubestore
tailscale.com/kube/types from tailscale.com/cmd/k8s-operator+
tailscale.com/licenses from tailscale.com/client/web tailscale.com/licenses from tailscale.com/client/web
tailscale.com/log/filelogger from tailscale.com/logpolicy tailscale.com/log/filelogger from tailscale.com/logpolicy
tailscale.com/log/sockstatlog from tailscale.com/ipn/ipnlocal tailscale.com/log/sockstatlog from tailscale.com/ipn/ipnlocal

@ -23,7 +23,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/reconcile"
"tailscale.com/ipn" "tailscale.com/ipn"
"tailscale.com/kube" kubetypes "tailscale.com/kube/types"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/util/clientmetric" "tailscale.com/util/clientmetric"
"tailscale.com/util/set" "tailscale.com/util/set"
@ -54,7 +54,7 @@ type IngressReconciler struct {
var ( var (
// gaugeIngressResources tracks the number of ingress resources that we're // gaugeIngressResources tracks the number of ingress resources that we're
// currently managing. // currently managing.
gaugeIngressResources = clientmetric.NewGauge(kube.MetricIngressResourceCount) gaugeIngressResources = clientmetric.NewGauge(kubetypes.MetricIngressResourceCount)
) )
func (a *IngressReconciler) Reconcile(ctx context.Context, req reconcile.Request) (_ reconcile.Result, err error) { func (a *IngressReconciler) Reconcile(ctx context.Context, req reconcile.Request) (_ reconcile.Result, err error) {

@ -17,7 +17,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/client/fake"
"tailscale.com/ipn" "tailscale.com/ipn"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube" kubetypes "tailscale.com/kube/types"
"tailscale.com/types/ptr" "tailscale.com/types/ptr"
"tailscale.com/util/mak" "tailscale.com/util/mak"
) )
@ -94,7 +94,7 @@ func TestTailscaleIngress(t *testing.T) {
namespace: "default", namespace: "default",
parentType: "ingress", parentType: "ingress",
hostname: "default-test", hostname: "default-test",
app: kube.AppIngressResource, app: kubetypes.AppIngressResource,
} }
serveConfig := &ipn.ServeConfig{ serveConfig := &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{443: {HTTPS: true}}, TCP: map[uint16]*ipn.TCPPortHandler{443: {HTTPS: true}},
@ -226,7 +226,7 @@ func TestTailscaleIngressWithProxyClass(t *testing.T) {
namespace: "default", namespace: "default",
parentType: "ingress", parentType: "ingress",
hostname: "default-test", hostname: "default-test",
app: kube.AppIngressResource, app: kubetypes.AppIngressResource,
} }
serveConfig := &ipn.ServeConfig{ serveConfig := &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{443: {HTTPS: true}}, TCP: map[uint16]*ipn.TCPPortHandler{443: {HTTPS: true}},

@ -28,7 +28,7 @@ import (
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
tsoperator "tailscale.com/k8s-operator" tsoperator "tailscale.com/k8s-operator"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube" kubetypes "tailscale.com/kube/types"
"tailscale.com/tstime" "tailscale.com/tstime"
"tailscale.com/util/clientmetric" "tailscale.com/util/clientmetric"
"tailscale.com/util/set" "tailscale.com/util/set"
@ -63,7 +63,7 @@ type NameserverReconciler struct {
managedNameservers set.Slice[types.UID] // one or none managedNameservers set.Slice[types.UID] // one or none
} }
var gaugeNameserverResources = clientmetric.NewGauge(kube.MetricNameserverCount) var gaugeNameserverResources = clientmetric.NewGauge(kubetypes.MetricNameserverCount)
func (a *NameserverReconciler) Reconcile(ctx context.Context, req reconcile.Request) (res reconcile.Result, err error) { func (a *NameserverReconciler) Reconcile(ctx context.Context, req reconcile.Request) (res reconcile.Result, err error) {
logger := a.logger.With("dnsConfig", req.Name) logger := a.logger.With("dnsConfig", req.Name)

@ -39,7 +39,7 @@ import (
"tailscale.com/ipn" "tailscale.com/ipn"
"tailscale.com/ipn/store/kubestore" "tailscale.com/ipn/store/kubestore"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube" kubetypes "tailscale.com/kube/types"
"tailscale.com/tsnet" "tailscale.com/tsnet"
"tailscale.com/tstime" "tailscale.com/tstime"
"tailscale.com/types/logger" "tailscale.com/types/logger"
@ -88,9 +88,9 @@ func main() {
// https://tailscale.com/kb/1236/kubernetes-operator/?q=kubernetes#accessing-the-kubernetes-control-plane-using-an-api-server-proxy. // https://tailscale.com/kb/1236/kubernetes-operator/?q=kubernetes#accessing-the-kubernetes-control-plane-using-an-api-server-proxy.
mode := parseAPIProxyMode() mode := parseAPIProxyMode()
if mode == apiserverProxyModeDisabled { if mode == apiserverProxyModeDisabled {
hostinfo.SetApp(kube.AppOperator) hostinfo.SetApp(kubetypes.AppOperator)
} else { } else {
hostinfo.SetApp(kube.AppAPIServerProxy) hostinfo.SetApp(kubetypes.AppAPIServerProxy)
} }
s, tsClient := initTSNet(zlog) s, tsClient := initTSNet(zlog)

@ -22,7 +22,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/client/fake"
"sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/reconcile"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube" kubetypes "tailscale.com/kube/types"
"tailscale.com/net/dns/resolvconffile" "tailscale.com/net/dns/resolvconffile"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/tstime" "tailscale.com/tstime"
@ -124,7 +124,7 @@ func TestLoadBalancerClass(t *testing.T) {
parentType: "svc", parentType: "svc",
hostname: "default-test", hostname: "default-test",
clusterTargetIP: "10.20.30.40", clusterTargetIP: "10.20.30.40",
app: kube.AppIngressProxy, app: kubetypes.AppIngressProxy,
} }
expectEqual(t, fc, expectedSecret(t, fc, opts), nil) expectEqual(t, fc, expectedSecret(t, fc, opts), nil)
@ -262,7 +262,7 @@ func TestTailnetTargetFQDNAnnotation(t *testing.T) {
parentType: "svc", parentType: "svc",
tailnetTargetFQDN: tailnetTargetFQDN, tailnetTargetFQDN: tailnetTargetFQDN,
hostname: "default-test", hostname: "default-test",
app: kube.AppEgressProxy, app: kubetypes.AppEgressProxy,
} }
expectEqual(t, fc, expectedSecret(t, fc, o), nil) expectEqual(t, fc, expectedSecret(t, fc, o), nil)
@ -374,7 +374,7 @@ func TestTailnetTargetIPAnnotation(t *testing.T) {
parentType: "svc", parentType: "svc",
tailnetTargetIP: tailnetTargetIP, tailnetTargetIP: tailnetTargetIP,
hostname: "default-test", hostname: "default-test",
app: kube.AppEgressProxy, app: kubetypes.AppEgressProxy,
} }
expectEqual(t, fc, expectedSecret(t, fc, o), nil) expectEqual(t, fc, expectedSecret(t, fc, o), nil)
@ -483,7 +483,7 @@ func TestAnnotations(t *testing.T) {
parentType: "svc", parentType: "svc",
hostname: "default-test", hostname: "default-test",
clusterTargetIP: "10.20.30.40", clusterTargetIP: "10.20.30.40",
app: kube.AppIngressProxy, app: kubetypes.AppIngressProxy,
} }
expectEqual(t, fc, expectedSecret(t, fc, o), nil) expectEqual(t, fc, expectedSecret(t, fc, o), nil)
@ -589,7 +589,7 @@ func TestAnnotationIntoLB(t *testing.T) {
parentType: "svc", parentType: "svc",
hostname: "default-test", hostname: "default-test",
clusterTargetIP: "10.20.30.40", clusterTargetIP: "10.20.30.40",
app: kube.AppIngressProxy, app: kubetypes.AppIngressProxy,
} }
expectEqual(t, fc, expectedSecret(t, fc, o), nil) expectEqual(t, fc, expectedSecret(t, fc, o), nil)
@ -719,7 +719,7 @@ func TestLBIntoAnnotation(t *testing.T) {
parentType: "svc", parentType: "svc",
hostname: "default-test", hostname: "default-test",
clusterTargetIP: "10.20.30.40", clusterTargetIP: "10.20.30.40",
app: kube.AppIngressProxy, app: kubetypes.AppIngressProxy,
} }
expectEqual(t, fc, expectedSecret(t, fc, o), nil) expectEqual(t, fc, expectedSecret(t, fc, o), nil)
@ -859,7 +859,7 @@ func TestCustomHostname(t *testing.T) {
parentType: "svc", parentType: "svc",
hostname: "reindeer-flotilla", hostname: "reindeer-flotilla",
clusterTargetIP: "10.20.30.40", clusterTargetIP: "10.20.30.40",
app: kube.AppIngressProxy, app: kubetypes.AppIngressProxy,
} }
expectEqual(t, fc, expectedSecret(t, fc, o), nil) expectEqual(t, fc, expectedSecret(t, fc, o), nil)
@ -972,7 +972,7 @@ func TestCustomPriorityClassName(t *testing.T) {
hostname: "tailscale-critical", hostname: "tailscale-critical",
priorityClassName: "custom-priority-class-name", priorityClassName: "custom-priority-class-name",
clusterTargetIP: "10.20.30.40", clusterTargetIP: "10.20.30.40",
app: kube.AppIngressProxy, app: kubetypes.AppIngressProxy,
} }
expectEqual(t, fc, expectedSTS(t, fc, o), removeHashAnnotation) expectEqual(t, fc, expectedSTS(t, fc, o), removeHashAnnotation)
@ -1041,7 +1041,7 @@ func TestProxyClassForService(t *testing.T) {
parentType: "svc", parentType: "svc",
hostname: "default-test", hostname: "default-test",
clusterTargetIP: "10.20.30.40", clusterTargetIP: "10.20.30.40",
app: kube.AppIngressProxy, app: kubetypes.AppIngressProxy,
} }
expectEqual(t, fc, expectedSecret(t, fc, opts), nil) expectEqual(t, fc, expectedSecret(t, fc, opts), nil)
expectEqual(t, fc, expectedHeadlessService(shortName, "svc"), nil) expectEqual(t, fc, expectedHeadlessService(shortName, "svc"), nil)
@ -1135,7 +1135,7 @@ func TestDefaultLoadBalancer(t *testing.T) {
parentType: "svc", parentType: "svc",
hostname: "default-test", hostname: "default-test",
clusterTargetIP: "10.20.30.40", clusterTargetIP: "10.20.30.40",
app: kube.AppIngressProxy, app: kubetypes.AppIngressProxy,
} }
expectEqual(t, fc, expectedSTS(t, fc, o), removeHashAnnotation) expectEqual(t, fc, expectedSTS(t, fc, o), removeHashAnnotation)
@ -1192,7 +1192,7 @@ func TestProxyFirewallMode(t *testing.T) {
hostname: "default-test", hostname: "default-test",
firewallMode: "nftables", firewallMode: "nftables",
clusterTargetIP: "10.20.30.40", clusterTargetIP: "10.20.30.40",
app: kube.AppIngressProxy, app: kubetypes.AppIngressProxy,
} }
expectEqual(t, fc, expectedSTS(t, fc, o), removeHashAnnotation) expectEqual(t, fc, expectedSTS(t, fc, o), removeHashAnnotation)
} }
@ -1247,7 +1247,7 @@ func TestTailscaledConfigfileHash(t *testing.T) {
hostname: "default-test", hostname: "default-test",
clusterTargetIP: "10.20.30.40", clusterTargetIP: "10.20.30.40",
confFileHash: "e09bededa0379920141cbd0b0dbdf9b8b66545877f9e8397423f5ce3e1ba439e", confFileHash: "e09bededa0379920141cbd0b0dbdf9b8b66545877f9e8397423f5ce3e1ba439e",
app: kube.AppIngressProxy, app: kubetypes.AppIngressProxy,
} }
expectEqual(t, fc, expectedSTS(t, fc, o), nil) expectEqual(t, fc, expectedSTS(t, fc, o), nil)
@ -1542,7 +1542,7 @@ func Test_externalNameService(t *testing.T) {
parentType: "svc", parentType: "svc",
hostname: "default-test", hostname: "default-test",
clusterTargetDNS: "foo.com", clusterTargetDNS: "foo.com",
app: kube.AppIngressProxy, app: kubetypes.AppIngressProxy,
} }
expectEqual(t, fc, expectedSecret(t, fc, opts), nil) expectEqual(t, fc, expectedSecret(t, fc, opts), nil)

@ -23,7 +23,7 @@ import (
"tailscale.com/client/tailscale" "tailscale.com/client/tailscale"
"tailscale.com/client/tailscale/apitype" "tailscale.com/client/tailscale/apitype"
ksr "tailscale.com/k8s-operator/sessionrecording" ksr "tailscale.com/k8s-operator/sessionrecording"
tskube "tailscale.com/kube" kubetypes "tailscale.com/kube/types"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/tsnet" "tailscale.com/tsnet"
"tailscale.com/util/clientmetric" "tailscale.com/util/clientmetric"
@ -339,10 +339,10 @@ const (
func addImpersonationHeaders(r *http.Request, log *zap.SugaredLogger) error { func addImpersonationHeaders(r *http.Request, log *zap.SugaredLogger) error {
log = log.With("remote", r.RemoteAddr) log = log.With("remote", r.RemoteAddr)
who := whoIsKey.Value(r.Context()) who := whoIsKey.Value(r.Context())
rules, err := tailcfg.UnmarshalCapJSON[tskube.KubernetesCapRule](who.CapMap, tailcfg.PeerCapabilityKubernetes) rules, err := tailcfg.UnmarshalCapJSON[kubetypes.KubernetesCapRule](who.CapMap, tailcfg.PeerCapabilityKubernetes)
if len(rules) == 0 && err == nil { if len(rules) == 0 && err == nil {
// Try the old capability name for backwards compatibility. // Try the old capability name for backwards compatibility.
rules, err = tailcfg.UnmarshalCapJSON[tskube.KubernetesCapRule](who.CapMap, oldCapabilityName) rules, err = tailcfg.UnmarshalCapJSON[kubetypes.KubernetesCapRule](who.CapMap, oldCapabilityName)
} }
if err != nil { if err != nil {
return fmt.Errorf("failed to unmarshal capability: %v", err) return fmt.Errorf("failed to unmarshal capability: %v", err)
@ -392,7 +392,7 @@ func determineRecorderConfig(who *apitype.WhoIsResponse) (failOpen bool, recorde
return false, nil, errors.New("[unexpected] cannot determine caller") return false, nil, errors.New("[unexpected] cannot determine caller")
} }
failOpen = true failOpen = true
rules, err := tailcfg.UnmarshalCapJSON[tskube.KubernetesCapRule](who.CapMap, tailcfg.PeerCapabilityKubernetes) rules, err := tailcfg.UnmarshalCapJSON[kubetypes.KubernetesCapRule](who.CapMap, tailcfg.PeerCapabilityKubernetes)
if err != nil { if err != nil {
return failOpen, nil, fmt.Errorf("failed to unmarshal Kubernetes capability: %w", err) return failOpen, nil, fmt.Errorf("failed to unmarshal Kubernetes capability: %w", err)
} }

@ -31,7 +31,7 @@ import (
"tailscale.com/ipn" "tailscale.com/ipn"
tsoperator "tailscale.com/k8s-operator" tsoperator "tailscale.com/k8s-operator"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube" kubetypes "tailscale.com/kube/types"
"tailscale.com/net/netutil" "tailscale.com/net/netutil"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/opt" "tailscale.com/types/opt"
@ -626,16 +626,16 @@ func (a *tailscaleSTSReconciler) reconcileSTS(ctx context.Context, logger *zap.S
func appInfoForProxy(cfg *tailscaleSTSConfig) (string, error) { func appInfoForProxy(cfg *tailscaleSTSConfig) (string, error) {
if cfg.ClusterTargetDNSName != "" || cfg.ClusterTargetIP != "" { if cfg.ClusterTargetDNSName != "" || cfg.ClusterTargetIP != "" {
return kube.AppIngressProxy, nil return kubetypes.AppIngressProxy, nil
} }
if cfg.TailnetTargetFQDN != "" || cfg.TailnetTargetIP != "" { if cfg.TailnetTargetFQDN != "" || cfg.TailnetTargetIP != "" {
return kube.AppEgressProxy, nil return kubetypes.AppEgressProxy, nil
} }
if cfg.ServeConfig != nil { if cfg.ServeConfig != nil {
return kube.AppIngressResource, nil return kubetypes.AppIngressResource, nil
} }
if cfg.Connector != nil { if cfg.Connector != nil {
return kube.AppConnector, nil return kubetypes.AppConnector, nil
} }
return "", errors.New("unable to determine proxy type") return "", errors.New("unable to determine proxy type")
} }

@ -25,7 +25,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/reconcile"
tsoperator "tailscale.com/k8s-operator" tsoperator "tailscale.com/k8s-operator"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube" kubetypes "tailscale.com/kube/types"
"tailscale.com/net/dns/resolvconffile" "tailscale.com/net/dns/resolvconffile"
"tailscale.com/tstime" "tailscale.com/tstime"
"tailscale.com/util/clientmetric" "tailscale.com/util/clientmetric"
@ -70,10 +70,10 @@ type ServiceReconciler struct {
var ( var (
// gaugeEgressProxies tracks the number of egress proxies that we're // gaugeEgressProxies tracks the number of egress proxies that we're
// currently managing. // currently managing.
gaugeEgressProxies = clientmetric.NewGauge(kube.MetricEgressProxyCount) gaugeEgressProxies = clientmetric.NewGauge(kubetypes.MetricEgressProxyCount)
// gaugeIngressProxies tracks the number of ingress proxies that we're // gaugeIngressProxies tracks the number of ingress proxies that we're
// currently managing. // currently managing.
gaugeIngressProxies = clientmetric.NewGauge(kube.MetricIngressProxyCount) gaugeIngressProxies = clientmetric.NewGauge(kubetypes.MetricIngressProxyCount)
) )
func childResourceLabels(name, ns, typ string) map[string]string { func childResourceLabels(name, ns, typ string) map[string]string {

@ -50,7 +50,7 @@ tailscale.com/cmd/stund dependencies: (generated by github.com/tailscale/depawar
google.golang.org/protobuf/types/known/timestamppb from github.com/prometheus/client_golang/prometheus+ google.golang.org/protobuf/types/known/timestamppb from github.com/prometheus/client_golang/prometheus+
tailscale.com from tailscale.com/version tailscale.com from tailscale.com/version
tailscale.com/envknob from tailscale.com/tsweb+ tailscale.com/envknob from tailscale.com/tsweb+
tailscale.com/kube from tailscale.com/envknob tailscale.com/kube/types from tailscale.com/envknob
tailscale.com/metrics from tailscale.com/net/stunserver+ tailscale.com/metrics from tailscale.com/net/stunserver+
tailscale.com/net/netaddr from tailscale.com/net/tsaddr tailscale.com/net/netaddr from tailscale.com/net/tsaddr
tailscale.com/net/stun from tailscale.com/net/stunserver tailscale.com/net/stun from tailscale.com/net/stunserver
@ -75,7 +75,6 @@ tailscale.com/cmd/stund dependencies: (generated by github.com/tailscale/depawar
tailscale.com/util/dnsname from tailscale.com/tailcfg tailscale.com/util/dnsname from tailscale.com/tailcfg
tailscale.com/util/fastuuid from tailscale.com/tsweb tailscale.com/util/fastuuid from tailscale.com/tsweb
tailscale.com/util/lineread from tailscale.com/version/distro tailscale.com/util/lineread from tailscale.com/version/distro
tailscale.com/util/multierr from tailscale.com/kube
tailscale.com/util/nocasemaps from tailscale.com/types/ipproto tailscale.com/util/nocasemaps from tailscale.com/types/ipproto
tailscale.com/util/slicesx from tailscale.com/tailcfg tailscale.com/util/slicesx from tailscale.com/tailcfg
tailscale.com/util/vizerror from tailscale.com/tailcfg+ tailscale.com/util/vizerror from tailscale.com/tailcfg+
@ -131,7 +130,7 @@ tailscale.com/cmd/stund dependencies: (generated by github.com/tailscale/depawar
crypto/sha512 from crypto/ecdsa+ crypto/sha512 from crypto/ecdsa+
crypto/subtle from crypto/aes+ crypto/subtle from crypto/aes+
crypto/tls from net/http+ crypto/tls from net/http+
crypto/x509 from crypto/tls+ crypto/x509 from crypto/tls
crypto/x509/pkix from crypto/x509 crypto/x509/pkix from crypto/x509
database/sql/driver from github.com/google/uuid database/sql/driver from github.com/google/uuid
embed from crypto/internal/nistec+ embed from crypto/internal/nistec+

@ -98,7 +98,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
tailscale.com/internal/noiseconn from tailscale.com/cmd/tailscale/cli tailscale.com/internal/noiseconn from tailscale.com/cmd/tailscale/cli
tailscale.com/ipn from tailscale.com/client/tailscale+ tailscale.com/ipn from tailscale.com/client/tailscale+
tailscale.com/ipn/ipnstate from tailscale.com/client/tailscale+ tailscale.com/ipn/ipnstate from tailscale.com/client/tailscale+
tailscale.com/kube from tailscale.com/envknob tailscale.com/kube/types from tailscale.com/envknob
tailscale.com/licenses from tailscale.com/client/web+ tailscale.com/licenses from tailscale.com/client/web+
tailscale.com/metrics from tailscale.com/derp+ tailscale.com/metrics from tailscale.com/derp+
tailscale.com/net/captivedetection from tailscale.com/net/netcheck tailscale.com/net/captivedetection from tailscale.com/net/netcheck

@ -279,7 +279,9 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
L tailscale.com/ipn/store/awsstore from tailscale.com/ipn/store L tailscale.com/ipn/store/awsstore from tailscale.com/ipn/store
L tailscale.com/ipn/store/kubestore from tailscale.com/ipn/store L tailscale.com/ipn/store/kubestore from tailscale.com/ipn/store
tailscale.com/ipn/store/mem from tailscale.com/ipn/ipnlocal+ tailscale.com/ipn/store/mem from tailscale.com/ipn/ipnlocal+
tailscale.com/kube from tailscale.com/ipn/store/kubestore+ L tailscale.com/kube/api from tailscale.com/ipn/store/kubestore+
L tailscale.com/kube/client from tailscale.com/ipn/store/kubestore
tailscale.com/kube/types from tailscale.com/envknob
tailscale.com/licenses from tailscale.com/client/web tailscale.com/licenses from tailscale.com/client/web
tailscale.com/log/filelogger from tailscale.com/logpolicy tailscale.com/log/filelogger from tailscale.com/logpolicy
tailscale.com/log/sockstatlog from tailscale.com/ipn/ipnlocal tailscale.com/log/sockstatlog from tailscale.com/ipn/ipnlocal

@ -31,7 +31,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"tailscale.com/kube" kubetypes "tailscale.com/kube/types"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/version" "tailscale.com/version"
"tailscale.com/version/distro" "tailscale.com/version/distro"
@ -410,7 +410,7 @@ func TKASkipSignatureCheck() bool { return Bool("TS_UNSAFE_SKIP_NKS_VERIFICATION
// Kubernetes Operator components. // Kubernetes Operator components.
func App() string { func App() string {
a := os.Getenv("TS_INTERNAL_APP") a := os.Getenv("TS_INTERNAL_APP")
if a == kube.AppConnector || a == kube.AppEgressProxy || a == kube.AppIngressProxy || a == kube.AppIngressResource { if a == kubetypes.AppConnector || a == kubetypes.AppEgressProxy || a == kubetypes.AppIngressProxy || a == kubetypes.AppIngressResource {
return a return a
} }
return "" return ""

@ -13,20 +13,21 @@ import (
"time" "time"
"tailscale.com/ipn" "tailscale.com/ipn"
"tailscale.com/kube" kubeapi "tailscale.com/kube/api"
kubeclient "tailscale.com/kube/client"
"tailscale.com/types/logger" "tailscale.com/types/logger"
) )
// Store is an ipn.StateStore that uses a Kubernetes Secret for persistence. // Store is an ipn.StateStore that uses a Kubernetes Secret for persistence.
type Store struct { type Store struct {
client kube.Client client kubeclient.Client
canPatch bool canPatch bool
secretName string secretName string
} }
// New returns a new Store that persists to the named secret. // New returns a new Store that persists to the named secret.
func New(_ logger.Logf, secretName string) (*Store, error) { func New(_ logger.Logf, secretName string) (*Store, error) {
c, err := kube.New() c, err := kubeclient.New()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -58,7 +59,7 @@ func (s *Store) ReadState(id ipn.StateKey) ([]byte, error) {
secret, err := s.client.GetSecret(ctx, s.secretName) secret, err := s.client.GetSecret(ctx, s.secretName)
if err != nil { if err != nil {
if st, ok := err.(*kube.Status); ok && st.Code == 404 { if st, ok := err.(*kubeapi.Status); ok && st.Code == 404 {
return nil, ipn.ErrStateNotExist return nil, ipn.ErrStateNotExist
} }
return nil, err return nil, err
@ -88,13 +89,13 @@ func (s *Store) WriteState(id ipn.StateKey, bs []byte) error {
secret, err := s.client.GetSecret(ctx, s.secretName) secret, err := s.client.GetSecret(ctx, s.secretName)
if err != nil { if err != nil {
if kube.IsNotFoundErr(err) { if kubeclient.IsNotFoundErr(err) {
return s.client.CreateSecret(ctx, &kube.Secret{ return s.client.CreateSecret(ctx, &kubeapi.Secret{
TypeMeta: kube.TypeMeta{ TypeMeta: kubeapi.TypeMeta{
APIVersion: "v1", APIVersion: "v1",
Kind: "Secret", Kind: "Secret",
}, },
ObjectMeta: kube.ObjectMeta{ ObjectMeta: kubeapi.ObjectMeta{
Name: s.secretName, Name: s.secretName,
}, },
Data: map[string][]byte{ Data: map[string][]byte{
@ -106,7 +107,7 @@ func (s *Store) WriteState(id ipn.StateKey, bs []byte) error {
} }
if s.canPatch { if s.canPatch {
if len(secret.Data) == 0 { // if user has pre-created a blank Secret if len(secret.Data) == 0 { // if user has pre-created a blank Secret
m := []kube.JSONPatch{ m := []kubeclient.JSONPatch{
{ {
Op: "add", Op: "add",
Path: "/data", Path: "/data",
@ -118,7 +119,7 @@ func (s *Store) WriteState(id ipn.StateKey, bs []byte) error {
} }
return nil return nil
} }
m := []kube.JSONPatch{ m := []kubeclient.JSONPatch{
{ {
Op: "add", Op: "add",
Path: "/data/" + sanitizeKey(id), Path: "/data/" + sanitizeKey(id),

@ -1,7 +1,11 @@
// Copyright (c) Tailscale Inc & AUTHORS // Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
package kube // Package api contains Kubernetes API types for internal consumption.
// These types are split into a separate package for consumption of
// non-Kubernetes shared libraries and binaries. Be mindful of not increasing
// dependency size for those consumers when adding anything new here.
package api
import "time" import "time"

@ -1,10 +1,13 @@
// Copyright (c) Tailscale Inc & AUTHORS // Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Package kube provides a client to interact with Kubernetes. // Package client provides a client to interact with Kubernetes.
// This package is Tailscale-internal and not meant for external consumption. // This package is Tailscale-internal and not meant for external consumption.
// Further, the API should not be considered stable. // Further, the API should not be considered stable.
package kube // Client is split into a separate package for consumption of
// non-Kubernetes shared libraries and binaries. Be mindful of not increasing
// dependency size for those consumers when adding anything new here.
package client
import ( import (
"bytes" "bytes"
@ -23,6 +26,7 @@ import (
"sync" "sync"
"time" "time"
kubeapi "tailscale.com/kube/api"
"tailscale.com/util/multierr" "tailscale.com/util/multierr"
) )
@ -50,10 +54,10 @@ func readFile(n string) ([]byte, error) {
// Client handles connections to Kubernetes. // Client handles connections to Kubernetes.
// It expects to be run inside a cluster. // It expects to be run inside a cluster.
type Client interface { type Client interface {
GetSecret(context.Context, string) (*Secret, error) GetSecret(context.Context, string) (*kubeapi.Secret, error)
UpdateSecret(context.Context, *Secret) error UpdateSecret(context.Context, *kubeapi.Secret) error
CreateSecret(context.Context, *Secret) error CreateSecret(context.Context, *kubeapi.Secret) error
StrategicMergePatchSecret(context.Context, string, *Secret, string) error StrategicMergePatchSecret(context.Context, string, *kubeapi.Secret, string) error
JSONPatchSecret(context.Context, string, []JSONPatch) error JSONPatchSecret(context.Context, string, []JSONPatch) error
CheckSecretPermissions(context.Context, string) (bool, bool, error) CheckSecretPermissions(context.Context, string) (bool, bool, error)
SetDialer(dialer func(context.Context, string, string) (net.Conn, error)) SetDialer(dialer func(context.Context, string, string) (net.Conn, error))
@ -144,7 +148,7 @@ func getError(resp *http.Response) error {
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#http-status-codes // https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#http-status-codes
return nil return nil
} }
st := &Status{} st := &kubeapi.Status{}
if err := json.NewDecoder(resp.Body).Decode(st); err != nil { if err := json.NewDecoder(resp.Body).Decode(st); err != nil {
return err return err
} }
@ -178,7 +182,7 @@ func (c *client) doRequest(ctx context.Context, method, url string, in, out any,
} }
defer resp.Body.Close() defer resp.Body.Close()
if err := getError(resp); err != nil { if err := getError(resp); err != nil {
if st, ok := err.(*Status); ok && st.Code == 401 { if st, ok := err.(*kubeapi.Status); ok && st.Code == 401 {
c.expireToken() c.expireToken()
} }
return err return err
@ -220,8 +224,8 @@ func (c *client) newRequest(ctx context.Context, method, url string, in any) (*h
} }
// GetSecret fetches the secret from the Kubernetes API. // GetSecret fetches the secret from the Kubernetes API.
func (c *client) GetSecret(ctx context.Context, name string) (*Secret, error) { func (c *client) GetSecret(ctx context.Context, name string) (*kubeapi.Secret, error) {
s := &Secret{Data: make(map[string][]byte)} s := &kubeapi.Secret{Data: make(map[string][]byte)}
if err := c.doRequest(ctx, "GET", c.secretURL(name), nil, s); err != nil { if err := c.doRequest(ctx, "GET", c.secretURL(name), nil, s); err != nil {
return nil, err return nil, err
} }
@ -229,13 +233,13 @@ func (c *client) GetSecret(ctx context.Context, name string) (*Secret, error) {
} }
// CreateSecret creates a secret in the Kubernetes API. // CreateSecret creates a secret in the Kubernetes API.
func (c *client) CreateSecret(ctx context.Context, s *Secret) error { func (c *client) CreateSecret(ctx context.Context, s *kubeapi.Secret) error {
s.Namespace = c.ns s.Namespace = c.ns
return c.doRequest(ctx, "POST", c.secretURL(""), s, nil) return c.doRequest(ctx, "POST", c.secretURL(""), s, nil)
} }
// UpdateSecret updates a secret in the Kubernetes API. // UpdateSecret updates a secret in the Kubernetes API.
func (c *client) UpdateSecret(ctx context.Context, s *Secret) error { func (c *client) UpdateSecret(ctx context.Context, s *kubeapi.Secret) error {
return c.doRequest(ctx, "PUT", c.secretURL(s.Name), s, nil) return c.doRequest(ctx, "PUT", c.secretURL(s.Name), s, nil)
} }
@ -263,7 +267,7 @@ func (c *client) JSONPatchSecret(ctx context.Context, name string, patch []JSONP
// StrategicMergePatchSecret updates a secret in the Kubernetes API using a // StrategicMergePatchSecret updates a secret in the Kubernetes API using a
// strategic merge patch. // strategic merge patch.
// If a fieldManager is provided, it will be used to track the patch. // If a fieldManager is provided, it will be used to track the patch.
func (c *client) StrategicMergePatchSecret(ctx context.Context, name string, s *Secret, fieldManager string) error { func (c *client) StrategicMergePatchSecret(ctx context.Context, name string, s *kubeapi.Secret, fieldManager string) error {
surl := c.secretURL(name) surl := c.secretURL(name)
if fieldManager != "" { if fieldManager != "" {
uv := url.Values{ uv := url.Values{
@ -340,7 +344,7 @@ func (c *client) checkPermission(ctx context.Context, verb, secretName string) (
} }
func IsNotFoundErr(err error) bool { func IsNotFoundErr(err error) bool {
if st, ok := err.(*Status); ok && st.Code == 404 { if st, ok := err.(*kubeapi.Status); ok && st.Code == 404 {
return true return true
} }
return false return false

@ -1,34 +1,36 @@
// Copyright (c) Tailscale Inc & AUTHORS // Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
package kube package client
import ( import (
"context" "context"
"net" "net"
kubeapi "tailscale.com/kube/api"
) )
var _ Client = &FakeClient{} var _ Client = &FakeClient{}
type FakeClient struct { type FakeClient struct {
GetSecretImpl func(context.Context, string) (*Secret, error) GetSecretImpl func(context.Context, string) (*kubeapi.Secret, error)
CheckSecretPermissionsImpl func(ctx context.Context, name string) (bool, bool, error) CheckSecretPermissionsImpl func(ctx context.Context, name string) (bool, bool, error)
} }
func (fc *FakeClient) CheckSecretPermissions(ctx context.Context, name string) (bool, bool, error) { func (fc *FakeClient) CheckSecretPermissions(ctx context.Context, name string) (bool, bool, error) {
return fc.CheckSecretPermissionsImpl(ctx, name) return fc.CheckSecretPermissionsImpl(ctx, name)
} }
func (fc *FakeClient) GetSecret(ctx context.Context, name string) (*Secret, error) { func (fc *FakeClient) GetSecret(ctx context.Context, name string) (*kubeapi.Secret, error) {
return fc.GetSecretImpl(ctx, name) return fc.GetSecretImpl(ctx, name)
} }
func (fc *FakeClient) SetURL(_ string) {} func (fc *FakeClient) SetURL(_ string) {}
func (fc *FakeClient) SetDialer(dialer func(ctx context.Context, network, addr string) (net.Conn, error)) { func (fc *FakeClient) SetDialer(dialer func(ctx context.Context, network, addr string) (net.Conn, error)) {
} }
func (fc *FakeClient) StrategicMergePatchSecret(context.Context, string, *Secret, string) error { func (fc *FakeClient) StrategicMergePatchSecret(context.Context, string, *kubeapi.Secret, string) error {
return nil return nil
} }
func (fc *FakeClient) JSONPatchSecret(context.Context, string, []JSONPatch) error { func (fc *FakeClient) JSONPatchSecret(context.Context, string, []JSONPatch) error {
return nil return nil
} }
func (fc *FakeClient) UpdateSecret(context.Context, *Secret) error { return nil } func (fc *FakeClient) UpdateSecret(context.Context, *kubeapi.Secret) error { return nil }
func (fc *FakeClient) CreateSecret(context.Context, *Secret) error { return nil } func (fc *FakeClient) CreateSecret(context.Context, *kubeapi.Secret) error { return nil }

@ -1,7 +1,12 @@
// Copyright (c) Tailscale Inc & AUTHORS // Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
package kube // Package types contains types and constants related to the Tailscale
// Kubernetes Operator.
// These are split into a separate package for consumption of
// non-Kubernetes shared libraries and binaries. Be mindful of not increasing
// dependency size for those consumers when adding anything new here.
package types
import "net/netip" import "net/netip"

@ -1,7 +1,7 @@
// Copyright (c) Tailscale Inc & AUTHORS // Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
package kube package types
const ( const (
// Hostinfo App values for the Tailscale Kubernetes Operator components. // Hostinfo App values for the Tailscale Kubernetes Operator components.
Loading…
Cancel
Save