secret/kubeconfig created
workspaceshard.tenancy.kcp.io/boston created
[3J[H[2J# The kubectl kcp workspace plugin mainly delegates to the 'workspaces' virtual workspace
# in order to create, list, delete workspaces but also to retrieve a workspace kubeconfig
# that can then be added as a new context to the current kubeconfig

☸️ $ kubectl kcp workspace --help
Manages KCP workspaces

Usage:
  workspace [command]

Examples:

	# Shows the workspace you are currently using
	kubectl kcp workspace current

	# use a given workspace (this will change the current-context of your current KUBECONFIG)
	kubectl kcp workspace use

	# list all your personal workspaces
	kubectl kcp workspace list


Available Commands:
  completion  generate the autocompletion script for the specified shell
  create      Creates a new personal workspace
  current     Returns the name of the current workspace
  delete      Deletes a personal workspace
  help        Help about any command
  list        Returns the list of the personal workspaces of the user
  use         Uses the given workspace as the current workspace. Using - means previous workspace

Flags:
      --certificate-authority string                       Path to a cert file for the certificate authority
      --context string                                     The name of the kubeconfig context to use
  -h, --help                                               help for workspace
      --insecure-skip-tls-verify                           If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
      --password string                                    Password for basic authentication to the API server
      --server string                                      The address and port of the Kubernetes API server
      --tls-server-name string                             If provided, this name will be used to validate server certificate. If this is not provided, hostname used to contact the server is used.
      --token string                                       Bearer token for authentication to the API server
      --username string                                    Username for basic authentication to the API server
      --workspace-directory-certificate-authority string   Path to a cert file for the certificate authority for workspace directory context
      --workspace-directory-context string                 The name of the kubeconfig context to use for workspace directory context (default "workspace-directory")
      --workspace-directory-insecure-skip-tls-verify       If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure for workspace directory context
      --workspace-directory-password string                Password for basic authentication to the API server for workspace directory context
      --workspace-directory-server string                  The address and port of the Kubernetes API server for workspace directory context (default "https://127.0.0.1:6444/services/applications/personal")
      --workspace-directory-tls-server-name string         If provided, this name will be used to validate server certificate. If this is not provided, hostname used to contact the server is used. for workspace directory context
      --workspace-directory-token string                   Bearer token for authentication to the API server for workspace directory context
      --workspace-directory-username string                Username for basic authentication to the API server for workspace directory context

Use "workspace [command] --help" for more information about a command.
[3J[H[2J# Let's use a kubeconfig that contains only one context pointing to the virtual workspace
# and allowing to retrieve the workspaces owned by a user (== workspace directory)
☸️ $ more /home/dfestal/go/src/github.com/kcp-dev/kcp/manual-tests/workspaceKubectlPlugin-test/myKubeConfig
apiVersion: v1
clusters:
- cluster:
    insecure-skip-tls-verify: true
    server: https://127.0.0.1:6444/services/applications/personal
  name: workspace-directory
contexts:
- context:
    cluster: workspace-directory
    user: ""
  name: workspace-directory
current-context: ""
kind: Config
preferences: {}
users: null
[3J[H[2J# Let's create 2 workspaces for user-1
# Creating a workspace also creates the required cluster role and cluster role bindings
# in the underlying KCP organization workspace.

☸️ $ kubectl kcp workspace --token user-1-token create user-1-workspace-1
Workspace "user-1-workspace-1" created.
☸️ $ kubectl kcp workspace --token user-1-token create user-1-workspace-2
Workspace "user-1-workspace-2" created.

# The 2 workspaces are now part of user-1 personal workspaces and each one has a valid URL
# to access it directly in KCP.

☸️ $ kubectl kcp workspace --token user-1-token list
NAME                 PHASE    BASE URL
user-1-workspace-1   Active   https://127.0.0.1:6443/clusters/admin_user-1-workspace-1
user-1-workspace-2   Active   https://127.0.0.1:6443/clusters/admin_user-1-workspace-2

# And we confirm that user-2 cannot see them.

☸️ $ kubectl kcp workspace --token user-2-token list

# Now let user-1 switch to his first workspace to use it.
# Note that it is similar, at the KCP workspace level, to:
#     kubectl config use-content

☸️ $ kubectl kcp workspace --token user-1-token use user-1-workspace-1
Current personal workspace is "user-1-workspace-1".

# We can confirm that the current workspace is correctly set.
# That means that any subsequent call to kubectl will be performed against
# the current workspace with the user used when previously switching to the workspace
# (with the use command).

☸️ $ kubectl kcp workspace --token user-1-token current
Current personal workspace is "user-1-workspace-1".

# In other words, a new kubectl context, dedicated to this KCP workspace
# has been created in the current kubeconfig, and set as the current context.

☸️ $ kubectl config current-context
workspace.kcp.io/personal/user-1-workspace-1

# Now we can access the content of the current workspace with kubectl

# NOTE : Here and later on, the override of the user to use the admin user
# is only required temporarily, until the KCP workspace Auth PR is merged.
# When it is done, the user-1 user will automatically have access to the
# content of workspaces he owns.

☸️ $ kubectl --token admin-token create secret generic user-1-secret-1
secret/user-1-secret-1 created
☸️ $ kubectl --token admin-token  get secrets
NAME              TYPE     DATA   AGE
user-1-secret-1   Opaque   0      1s

# Let's prove that user-2 cannot access the content of user-1-workspace-1

☸️ $ kubectl --token user-2-token get secrets
Error from server (Forbidden): secrets is forbidden: User "user-2" cannot list resource "secrets" in API group "" in the namespace "default": workspace access not permitted

# Yes, only user-1 should have access to the his workspaces.

☸️ $ kubectl --token user-1-token get secrets
Error from server (Forbidden): secrets is forbidden: User "user-1" cannot list resource "secrets" in API group "" in the namespace "default": workspace access not permitted

# And in the updated kubeconfig, the current workspace context effectively
# uses user-1, since the use command was run by user-1

☸️ $ more myKubeConfig
apiVersion: v1
clusters:
- cluster:
    insecure-skip-tls-verify: true
    server: https://127.0.0.1:6444/services/applications/personal
  name: workspace-directory
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURXRENDQWtDZ0F3SUJBZ0lCQWpBTkJna3Foa2lHOXcwQkFRc0ZBREF5TVRBd0xnWURWUVFERENkaGNHbHoKWlhKMlpYSXRiRzl2Y0dKaFkyc3RZMnhwWlc1MExXTmhRREUyTkRNeU9URTNOamt3SGhjTk1qSXdNVEkzTVRJMQpOakE1V2hjTk1qTXdNVEkzTVRJMU5qQTVXakF2TVMwd0t3WURWUVFERENSaGNHbHpaWEoyWlhJdGJHOXZjR0poClkyc3RZMnhwWlc1MFFERTJORE15T1RFM05qa3dnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUsKQW9JQkFRQ3p2ZStjazZFVDhuWlc0bmIyU0hkTkd2OHR3dTVMenVFcThHZW5PYzgxTjk3MzhuRnFiWjhuNUtBRApVa2JtZFJnUkkzekZGcUNIVWlzMmQxQlhIQlQ2ejBVM0x0M2NyNFhrTmRkMUl5T3c4Q081RXNwcCtSaTI3emdVCkpPTnJVaHdFeUNlTzM5SmxwTzgxWU41c2hUR0hIN2dSUkJFOEkvOWlYYWlxOEplc1ErV3FvOXhyZ3NYNkJ1NFgKUWRnUnd6VFJLcHpNRGI0YUJjMkhkZ0NOWDdEZ0pBblhObStaSlJKQjlhN0JNU2Z3cEdZSS9uQ3gxRU91M0tlbQpCb0FjNmxpWWhwei9kUWVrLzVScm01NUN2VXJnWTcrTUVrYmovUmNyMlJyWHVmSERMS1pLbmpMejI0UlRTRlNwCm9xaFRSUGtOOHl0YlpjMmFZaGFLMVFWOTlHTkJBZ01CQUFHamZEQjZNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVQKQmdOVkhTVUVEREFLQmdnckJnRUZCUWNEQVRBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRlBnMQpNNHF6MHBuQ0R2ZTZvY1htNzFSak1jN2tNQ1FHQTFVZEVRUWRNQnVDR1dGd2FYTmxjblpsY2kxc2IyOXdZbUZqCmF5MWpiR2xsYm5Rd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFGaXFlTjB3NFRZaXRIVmdBaHphUE9Id2gzdFoKdVhqVU9NQUYzaEluME1EN1J2dk9kNTBub3hXTVdxYXVuVnpDWHJndllPcGJpY3VDVWljeGd2eTZCUEJ5b2E4UAo3TUl5WS9TcU83bFF0Y21IdzRGZGFhOHFTV2NMNm0xU2VONXZzZEU5dUtseFlWSFlMUURKNlljYUE2blN4UHdpCmlScG5oZ0NNUDF2ZzNHekFIald5SmRVRXh2UWt0VDBzZklXdkIyaUhraWRNRDF5RXd2R25rVlUrdFJFWTVxSk4KeGlvMkUxV0M4VlV6LzhmVGZjMzlIRjVpV21mVzdZMitYcGtaV3N5SnFDaENsVHlHaWZnMVRIWU1va0JpWUtTYwo4dHdKT3V3RUdxdkQ1emEvUXRNdFgxUWxLVE9iNk53aWZZb3VJNHZndVdTZ1NNMllTL2p6T2J5T2RIcz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0KTUlJRElUQ0NBZ21nQXdJQkFnSUJBVEFOQmdrcWhraUc5dzBCQVFzRkFEQXlNVEF3TGdZRFZRUUREQ2RoY0dsegpaWEoyWlhJdGJHOXZjR0poWTJzdFkyeHBaVzUwTFdOaFFERTJORE15T1RFM05qa3dIaGNOTWpJd01USTNNVEkxCk5qQTVXaGNOTWpNd01USTNNVEkxTmpBNVdqQXlNVEF3TGdZRFZRUUREQ2RoY0dselpYSjJaWEl0Ykc5dmNHSmgKWTJzdFkyeHBaVzUwTFdOaFFERTJORE15T1RFM05qa3dnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBdwpnZ0VLQW9JQkFRQ3cyOVVFTHU3OWlQc3RoRU9aL2plbzQrYzVjNGtZNDcwQnpIRVp5MDNtZW1FRFV6em10WFFMCmFVSDBqWXdsT0xWL001K1RFb3lQTkFwOTVhdjRKT2o2a0kwVWtLbm5rSFZLdkwrVEdkQ0QvQ3VBM2sxSzVURTAKS1ErY2FZcHJZUGlpYXVNVEUydVkvTGs5ajNmbEkxOVBxemplNzRHcXByckpNM2lnQzJJdzJYNGJ1aElOQ0czMQp4ODJ6dFdpakdVRTlrTFJaYXhLU1pOc0tFUVNxSS90OFY0K0pteVZQK0Z2eHErVng3MzZDRUo0SWdYczY2bmc4CmhrLzJIWW9xbG9qQVZhK2tNVERnVHkrOVozUzVnQU4zZHFGZUs1RjRCaW83UUxkdWd1OSs3emVBcHlNQm9iZVAKaWtCQThvRVYrUTQ4ZGJWK3YzU0RmOFU1R1NZZW9PTFZBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQwpwREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlQ0TlRPS3M5S1p3ZzczdXFIRjV1OVVZekhPCjVEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFaMDBQcG1rQmhnWExucUxaREtyaWc5Z215NkVzZDU4Zm5ncFUKd2pxblFlR0g4NXBTR215eUVwT01CeFFxeXl0Zi9LVDluUHRpYS9aYlAyRTVjYjVBUzk0NVBheFY0RHVYTEVQSgpRZ0tuSGFIOUlCcGI3UUVvVzRVdUVsWjZzV0ZORWxUZmlqUEZqYnRtNlRYNktRZGxCZloyRDluNmd3WFF5Unk5CnFId3AybCsyUFY1QWprMlZEbldtajlLRnJRNklNZmhlUE01UFlPMnVCeFkxaWIvRmNWYTNGRndIenp4K1FYajIKd0hSdjlYbnc2d3JiVUNFRmszekkybkJOeTVSck9BQjJsUDNidnNQWDJuZTRtbzFxbERYOGx2Y0JDZnMwMUF6egpIdHFlMVJzZDlJK0Q1MHRZdzBOdzFaMUtJaFlDaDJGUjcvTHVtbTFUU0dEMVRGdHpuUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
    server: https://127.0.0.1:6443/clusters/admin_user-1-workspace-1
    tls-server-name: apiserver-loopback-client
  name: workspace.kcp.io/personal/user-1-workspace-1
contexts:
- context:
    cluster: workspace-directory
    user: ""
  name: workspace-directory
- context:
    cluster: workspace.kcp.io/personal/user-1-workspace-1
    user: workspace.kcp.io/personal/user-1-workspace-1
  name: workspace.kcp.io/personal/user-1-workspace-1
current-context: workspace.kcp.io/personal/user-1-workspace-1
kind: Config
preferences: {}
users:
- name: workspace.kcp.io/personal/user-1-workspace-1
  user:
    token: user-1-token
[3J[H[2J
# Now let's switch to user-1 second workspace and see that the 2 workspaces
# don't mix their content

☸️ $ kubectl kcp workspace use user-1-workspace-2
Current personal workspace is "user-1-workspace-2".
☸️ $ kubectl --token admin-token get secrets
No resources found in default namespace.
☸️ $ kubectl --token admin-token create secret generic user-1-secret-2
secret/user-1-secret-2 created
☸️ $ kubectl --token admin-token get secrets
NAME              TYPE     DATA   AGE
user-1-secret-2   Opaque   0      1s

# Let's switch back to the previous workspace with '-'

☸️ $ kubectl kcp workspace use -
Current personal workspace is "user-1-workspace-1".

# And find back the user-1 first workspace content

☸️ $ kubectl --token admin-token get secrets
NAME              TYPE     DATA   AGE
user-1-secret-1   Opaque   0      31s
[3J[H[2J
# Finally let's create a workspace for user-2.
# We can specify the workspace it should inherit CRDs from,
# as well as switch directly to the new workspace with the 'use' argument

☸️ $ kubectl kcp workspace --token user-2-token create user-2-workspace-1 --inherit-from=user --use
Workspace "user-2-workspace-1" created.
Current personal workspace is "user-2-workspace-1".
☸️ $ kubectl --token admin-token create secret generic user-2-secret-1
secret/user-2-secret-1 created
☸️ $ kubectl --token admin-token get secrets
NAME              TYPE     DATA   AGE
user-2-secret-1   Opaque   0      2s

# As expected user-1 cannot see the contents of the current workspace owned by user-2

☸️ $ kubectl --token user-1-token get secrets
Error from server (Forbidden): secrets is forbidden: User "user-1" cannot list resource "secrets" in API group "" in the namespace "default": workspace access not permitted

# But more than that, user-1 cannot use a workspace owned by user-2
# since for user-1 it just doesn't exist.
# Ability for user-2 to share his workspace will be implemented later.

☸️ $ kubectl kcp workspace --token user-1-token use user-2-workspace1
Error: the server could not find the requested resource (get workspaces.tenancy.kcp.io user-2-workspace1)
