Skip to content

Commit

Permalink
docs: Add test for run-command.md
Browse files Browse the repository at this point in the history
Signed-off-by: Qasim Sarfraz <qasimsarfraz@microsoft.com>
  • Loading branch information
mqasimsarfraz committed Jan 8, 2024
1 parent 0eb3c4d commit 4dda796
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 31 deletions.
79 changes: 71 additions & 8 deletions .github/workflows/kubectl-aks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Azure Kubernetes Service kubectl plugin CI
env:
GO_VERSION: 1.18
AZURE_PREFIX: kubectl-aks-ci
AZURE_NODE_COUNT: 3 # multiple nodes are needed to allow running parallel 'run-command' against the same cluster
AZURE_NODE_COUNT: 4 # multiple nodes are needed to allow running parallel 'run-command' against the same cluster
concurrency:
# Only one workflow can run at a time unless
# we create a new AKS cluster per github_ref (branch)
Expand Down Expand Up @@ -114,7 +114,8 @@ jobs:
needs: [ build, lint, unit-tests ]
runs-on: ubuntu-latest
outputs:
nodes: ${{ steps.nodes.outputs.result }}
integration-nodes: ${{ steps.nodes.outputs.integration }}
documentation-nodes: ${{ steps.nodes.outputs.documentation }}
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -150,7 +151,10 @@ jobs:
id: nodes
shell: bash
run: |
echo "result=$(kubectl get nodes -o jsonpath={.items[*].metadata.name} | jq -R -s -c 'split(" ")')" >> $GITHUB_OUTPUT
NODES=$(kubectl get nodes -o jsonpath={.items[*].metadata.name} | jq -R -s -c 'split(" ")')
# Split nodes into integration and documentation groups to allow running parallel tests
echo "integration=$(echo $NODES | jq -c .[0:3])" >> $GITHUB_OUTPUT
echo "documentation=$(echo $NODES | jq -c .[3:4])" >> $GITHUB_OUTPUT
delete-aks-cluster:
name: Delete AKS cluster
Expand Down Expand Up @@ -201,7 +205,7 @@ jobs:
- name: Ensure enough nodes are available to run parallel tests
shell: bash
run: |
if [ $(echo '${{ needs.create-aks-cluster.outputs.nodes }}' | jq -r '. | length') -lt ${{ strategy.job-total }} ]; then
if [ $(echo '${{ needs.create-aks-cluster.outputs.integration-nodes }}' | jq -r '. | length') -lt ${{ strategy.job-total }} ]; then
echo "Not enough nodes to run parallel tests"
exit 1
fi
Expand Down Expand Up @@ -265,11 +269,70 @@ jobs:
export AZURE_RESOURCE_GROUP=${{ env.AZURE_PREFIX }}-rg
export AZURE_CLUSTER_NAME=${{ env.AZURE_PREFIX }}-${{ matrix.arch }}-cluster
export AZURE_SUBSCRIPTION_ID=${{ secrets.AZURE_AKS_SUBSCRIPTION_ID }}
export AZURE_NODE_NAME=$(echo '${{ needs.create-aks-cluster.outputs.nodes }}' | jq -r ".[${{ strategy.job-index }}]")
export AZURE_NODE_NAME=$(echo '${{ needs.create-aks-cluster.outputs.integration-nodes }}' | jq -r ".[${{ strategy.job-index }}]")
make integration-test -o kubectl-aks
documentation-test:
name: Run documentation tests
commands-documentation-test:
name: Run (commands) documentation tests
runs-on: ubuntu-latest
needs: [ build, unit-tests, create-aks-cluster ]
environment: aks
permissions:
# This is needed to use federated credentials:
# https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-cli%2Clinux#set-up-azure-login-with-openid-connect-authentication
id-token: write
contents: read
steps:
- name: Ensure enough nodes are available to run test
shell: bash
run: |
if [ $(echo '${{ needs.create-aks-cluster.outputs.documentation-nodes }}' | jq -r '. | length') -lt 1 ]; then
echo "Not enough nodes to run documentation tests"
exit 1
fi
- uses: actions/checkout@v3
- name: Setup go
uses: actions/setup-go@v4
with:
go-version: '>=1.20.0' # ie requires go 1.20+
check-latest: true
- name: Login to Azure
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_AKS_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_AKS_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_AKS_SUBSCRIPTION_ID }}
- name: Set AKS cluster context
uses: azure/aks-set-context@v3
with:
cluster-name: ${{ env.AZURE_PREFIX }}-amd64-cluster
resource-group: ${{ env.AZURE_PREFIX }}-rg
admin: false
- name: Get kubectl-aks from artifact
uses: actions/download-artifact@v3
with:
name: kubectl-aks-linux-amd64-tar-gz
- name: Prepare kubectl-aks binary
shell: bash
run: |
tar zxvf kubectl-aks-linux-amd64.tar.gz
chmod +x kubectl-aks
cp kubectl-aks /usr/local/bin/kubectl-aks
- name: Prepare variables files
run: |
VAR_FILES="./docs/run-command.ini"
for f in $VAR_FILES; do
echo "mySubID = ${{ secrets.AZURE_AKS_SUBSCRIPTION_ID }}" >> $f
echo "myRG = ${{ env.AZURE_PREFIX }}-rg" >> $f
echo "myCluster = ${{ env.AZURE_PREFIX }}-amd64-cluster" >> $f
echo "myNode = $(echo '${{ needs.create-aks-cluster.outputs.documentation-nodes }}' | jq -r ".[0]")" >> $f
done
- name: Run Documentation tests
run: |
make documentation-test-commands -o install
readme-documentation-test:
name: Run (README.md) documentation tests
runs-on: ubuntu-latest
needs: [ build, unit-tests ]
steps:
Expand All @@ -293,7 +356,7 @@ jobs:
cp ~/.krew/bin/kubectl-krew /usr/local/bin/kubectl-krew
echo "$HOME/.krew/bin" >> $GITHUB_PATH
- name: Run Documentation tests
run: make documentation-test -o kubectl-aks
run: make documentation-test-readme

release:
name: Release
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*.dll
*.so
*.dylib
*.ini
/kubectl-aks
/kubectl-aks-*-*

Expand Down
35 changes: 35 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Contributing to kubectl-aks

Welcome to the kubectl-aks repository! This document describes different ways to facilitate your contribution to the project.

If you would like to become a contributor to this project (or any other open source Microsoft project), see how to [Get Involved](https://opensource.microsoft.com/collaborate/).

## Testing

### integration tests

The integration test needs an AKS cluster to run against. After you have [created one](https://learn.microsoft.com/en-us/azure/aks/learn/quick-kubernetes-deploy-portal?tabs=azure-cli) and set up the access, use following command to run the integration test:

```
make integration-test
```

You will need to set `AZURE_RESOURCE_GROUP` and `AZURE_CLUSTER_NAME` environment variables to specify the AKS cluster to run against.

### documentation tests

The documentation tests are used to validate the documentation examples. You can run the documentation tests with the following command:

```
make documentation-test-readme
make documentation-test-commands
```

or you can select a specific markdown file of a command using:

```
DOCUMENTATION_TEST_FILES=./docs/run-command.md make documentation-test-commands
```

An INI file with all the required variables needs to be created to run the documentation tests. A sample INI file for [docs/run-command.md](docs/run-command.md)
is available [here](docs/run-command.ini.sample).
14 changes: 11 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,19 @@ integration-test: kubectl-aks
go test -v ./test/integration/... -integration

# Run documentation tests
.PHONY: documentation-test
documentation-test: kubectl-aks install-ie
ie --help > /dev/null || (echo "ie is not installed, please install it from https://github.com/Azure/InnovationEngine" && exit 1)
.PHONY: documentation-test-readme
documentation-test-readme: install-ie
ie execute README.md

DOCUMENTATION_TEST_FILES ?= \
./docs/run-command.md

.PHONY: documentation-test-commands
documentation-test-commands: install install-ie
for file in $(DOCUMENTATION_TEST_FILES); do \
ie execute $$file; \
done

# Clean
.PHONY: clean
clean:
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ service principal, you need to make sure that the permissions are granted.

## Contributing

For details on contributing to this repository, see the [contributing guide](CONTRIBUTING.md).

This project welcomes contributions and suggestions. Most contributions require
you to agree to a Contributor License Agreement (CLA) declaring that you have
the right to, and actually do, grant us the rights to use your contribution. For
Expand Down
4 changes: 4 additions & 0 deletions docs/run-command.ini.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mySubID = mySubID
myRG = myRG
myCluster = myCluster
myNode = myNode
95 changes: 75 additions & 20 deletions docs/run-command.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,29 @@ of running scripts in an Azure Linux VM also apply here.

## Regardless of the Kubernetes control plane status

When executing `run-command` without passing through Kubernetes, we need to provide the information of the node (VMSS instance) where we want to run the given command. To retrieve such information, we can use the [`config import`](./config.md#importing-configuration) command. Once we got it, we can select the node we want to use and all the subsequent `run-command` commands will be executed on that node:
When executing `run-command` without passing through Kubernetes, we need to provide the information of the node (VMSS instance) where we want to run the given command. To retrieve such information, we can use the [`config import`](./config.md#importing-configuration) command. Once we got it, we can select the node we want to use and all the subsequent `run-command` commands will be executed on that node.
To try it start by cleaning the current configuration (if any)

```bash
# Import the nodes information with the cluster information
$ kubectl aks config import --subscription mySubID --resource-group myRG --cluster-name myCluster
$ kubectl aks config show
kubectl aks config unset-all
```

Import the nodes information with the cluster information:

```bash
kubectl aks config import --subscription $mySubID --resource-group $myRG --cluster-name $myCluster
```

In case we want to print the imported information, we can use the `show` command:

```bash
kubectl aks config show
```

If importing the nodes information was successful, we should see something like this:

<!--expected_similarity=0.5-->
```
nodes:
aks-agentpool-12345678-vmss000000:
instance-id: "0"
Expand All @@ -26,12 +43,24 @@ nodes:
aks-agentpool-12345678-vmss000002:
instance-id: "2"
[...]
```

Start using one of above node e.g `aks-agentpool-12345678-vmss000000` we call it `$myNode` here:

```bash
kubectl aks config use-node $myNode
```

Execute the run-command, and it will be automatically executed in `aks-agentpool-12345678-vmss000000`:

# Start using one of those nodes
$ kubectl aks config use-node aks-agentpool-12345678-vmss000000
```bash
kubectl aks run-command "ip route"
```

# Execute the run-command, and it will be automatically executed in aks-agentpool-12345678-vmss000000
$ kubectl aks run-command "ip route"
The output should be similar to this:

<!--expected_similarity=0.8-->
```
default via 10.240.0.1 dev eth0 proto dhcp src 10.240.0.4 metric 100
10.240.0.0/16 dev eth0 proto kernel scope link src 10.240.0.4
10.244.2.2 dev calic38a36632c7 scope link
Expand All @@ -43,42 +72,68 @@ default via 10.240.0.1 dev eth0 proto dhcp src 10.240.0.4 metric 100
10.244.2.14 dev cali8eecb1f59c6 scope link
168.63.129.16 via 10.240.0.1 dev eth0 proto dhcp src 10.240.0.4 metric 100
169.254.169.254 via 10.240.0.1 dev eth0 proto dhcp src 10.240.0.4 metric 100
```

# Another command that will be still executed in aks-agentpool-12345678-vmss000000
$ kubectl aks run-command "hostname"
If we run another command, it will again be executed in `aks-agentpool-12345678-vmss000000`:

```bash
kubectl aks run-command "hostname"
```

The output should be similar to this:

<!--expected_similarity=0.8-->
```
aks-agentpool-12345678-vmss000000
```

Unset the current node to avoid conflict with flags or environment variables:

```bash
kubectl aks config unset-current-node
```

On the other side, if we already have the node (VMSS instance) information and we don't want/need to save it locally, we could pass it directly as following:

```bash
kubectl aks run-command "ip route" --id "/subscriptions/$SUBSCRIPTION/resourceGroups/$NODERESOURCEGROUP/providers/Microsoft.Compute/virtualMachineScaleSets/$VMSS/virtualmachines/$INSTANCEID"
<!-- TODO: Test following when we have a simple way to get instance information -->
```
kubectl aks run-command "ip route" --id "/subscriptions/$mySubID/resourceGroups/$myNRG/providers/Microsoft.Compute/virtualMachineScaleSets/$myVMSS/virtualmachines/$myInsId"
```

```bash
kubectl aks run-command "ip route" --subscription $SUBSCRIPTION --node-resource-group $NODERESOURCEGROUP --vmss $VMSS --instance-id $INSTANCEID
Or using the flags:

```
kubectl aks run-command "ip route" --subscription $mySubID --node-resource-group $myNRG --vmss $myVMSS --instance-id $myInsId
```

## Passing through Kubernetes

If we are debugging a node while the Kubernetes control plane is up and running, we can simply pass the node name to the `run-command` and it will internally retrieve all the data it needs from the API server to execute the command in that node:

```bash
kubectl aks run-command "ip route" --node aks-agentpool-12345678-vmss000000
kubectl aks run-command "ip route" --node $myNode
```

In addition, if we need to run multiple commands on a node, we can still use the [`config import`](./config.md#importing-configuration) command to import the information of all the nodes of our cluster, and this time we don't need to pass the cluster information as `run-command` will retrieve it from the API server:

```bash
# Import the nodes information from the API server
kubectl aks config import
```

Start using one of the nodes e.g `aks-agentpool-12345678-vmss000000` we call it `$myNode` here:

```bash
kubectl aks config use-node $myNode
```

# Start using one of the nodes
kubectl aks use-node aks-agentpool-12345678-vmss000000
Execute the run-command, and it will be automatically executed in `aks-agentpool-12345678-vmss000000`:

# Execute the run-command, and it will be automatically executed in aks-agentpool-12345678-vmss000000
```bash
kubectl aks run-command "ip route"
```

If we run another command, it will again be executed in `aks-agentpool-12345678-vmss000000`:

# Another command that will be still executed in aks-agentpool-12345678-vmss000000
```bash
kubectl aks run-command "hostname"
```

0 comments on commit 4dda796

Please sign in to comment.