From 4dda796dc21514680ab92d19b537ee704ad4f42b Mon Sep 17 00:00:00 2001 From: Qasim Sarfraz Date: Fri, 27 Oct 2023 14:42:01 +0200 Subject: [PATCH] docs: Add test for run-command.md Signed-off-by: Qasim Sarfraz --- .github/workflows/kubectl-aks.yml | 79 ++++++++++++++++++++++--- .gitignore | 1 + CONTRIBUTING.md | 35 ++++++++++++ Makefile | 14 ++++- README.md | 2 + docs/run-command.ini.sample | 4 ++ docs/run-command.md | 95 ++++++++++++++++++++++++------- 7 files changed, 199 insertions(+), 31 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 docs/run-command.ini.sample diff --git a/.github/workflows/kubectl-aks.yml b/.github/workflows/kubectl-aks.yml index 5a76bf3..611b487 100644 --- a/.github/workflows/kubectl-aks.yml +++ b/.github/workflows/kubectl-aks.yml @@ -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) @@ -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: @@ -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 @@ -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 @@ -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: @@ -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 diff --git a/.gitignore b/.gitignore index 22ae6f6..93d5b8d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ *.dll *.so *.dylib +*.ini /kubectl-aks /kubectl-aks-*-* diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..0ca9cd5 --- /dev/null +++ b/CONTRIBUTING.md @@ -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). diff --git a/Makefile b/Makefile index 7c81180..04262e4 100644 --- a/Makefile +++ b/Makefile @@ -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: diff --git a/README.md b/README.md index d966204..ce682e4 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/docs/run-command.ini.sample b/docs/run-command.ini.sample new file mode 100644 index 0000000..39c0ca1 --- /dev/null +++ b/docs/run-command.ini.sample @@ -0,0 +1,4 @@ +mySubID = mySubID +myRG = myRG +myCluster = myCluster +myNode = myNode diff --git a/docs/run-command.md b/docs/run-command.md index 5de8a50..ccc533b 100644 --- a/docs/run-command.md +++ b/docs/run-command.md @@ -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: + + +``` nodes: aks-agentpool-12345678-vmss000000: instance-id: "0" @@ -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: + + +``` 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 @@ -43,20 +72,38 @@ 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: + + +``` 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" + +``` +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 @@ -64,21 +111,29 @@ kubectl aks run-command "ip route" --subscription $SUBSCRIPTION --node-resource- 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" ```