merge master
Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
@ -1,6 +1,5 @@
|
||||
variables:
|
||||
YARN_CACHE_FOLDER: $(Pipeline.Workspace)/.yarn
|
||||
AZURE_CACHE_FOLDER: $(Pipeline.Workspace)/.azure-cache
|
||||
pr:
|
||||
- master
|
||||
- releases/*
|
||||
@ -29,14 +28,20 @@ jobs:
|
||||
inputs:
|
||||
versionSpec: $(node_version)
|
||||
displayName: Install Node.js
|
||||
- task: CacheBeta@0
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: yarn | $(Agent.OS) | yarn.lock
|
||||
restoreKeys: |
|
||||
yarn | "$(Agent.OS)"
|
||||
yarn
|
||||
path: $(YARN_CACHE_FOLDER)
|
||||
cacheHitVar: CACHE_RESTORED
|
||||
displayName: Cache Yarn packages
|
||||
- script: make install-deps
|
||||
- script: make node_modules
|
||||
displayName: Install dependencies
|
||||
- script: make build-npm
|
||||
displayName: Generate npm package
|
||||
- script: make -j2 build-extensions
|
||||
displayName: Build bundled extensions
|
||||
- script: make integration-win
|
||||
displayName: Run integration tests
|
||||
- script: make test-extensions
|
||||
@ -63,21 +68,24 @@ jobs:
|
||||
inputs:
|
||||
versionSpec: $(node_version)
|
||||
displayName: Install Node.js
|
||||
- task: CacheBeta@0
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: cache | $(Agent.OS) | yarn.lock
|
||||
path: $(AZURE_CACHE_FOLDER)
|
||||
cacheHitVar: CACHE_RESTORED
|
||||
key: yarn | $(Agent.OS) | yarn.lock
|
||||
restoreKeys: |
|
||||
yarn | "$(Agent.OS)"
|
||||
yarn
|
||||
path: $(YARN_CACHE_FOLDER)
|
||||
displayName: Cache Yarn packages
|
||||
- bash: |
|
||||
mkdir -p "$YARN_CACHE_FOLDER"
|
||||
tar -xzf "$AZURE_CACHE_FOLDER/yarn-cache.tar.gz" -C /
|
||||
displayName: "Unpack cache"
|
||||
condition: eq(variables.CACHE_RESTORED, 'true')
|
||||
- script: make install-deps
|
||||
- script: make node_modules
|
||||
displayName: Install dependencies
|
||||
- script: make build-npm
|
||||
displayName: Generate npm package
|
||||
- script: make -j2 build-extensions
|
||||
displayName: Build bundled extensions
|
||||
- script: make test
|
||||
displayName: Run tests
|
||||
- script: make test-extensions
|
||||
displayName: Run In-tree Extension tests
|
||||
- script: make integration-mac
|
||||
displayName: Run integration tests
|
||||
- script: make test-extensions
|
||||
@ -91,10 +99,6 @@ jobs:
|
||||
CSC_LINK: $(CSC_LINK)
|
||||
CSC_KEY_PASSWORD: $(CSC_KEY_PASSWORD)
|
||||
GH_TOKEN: $(GH_TOKEN)
|
||||
- bash: |
|
||||
mkdir -p "$AZURE_CACHE_FOLDER"
|
||||
tar -czf "$AZURE_CACHE_FOLDER/yarn-cache.tar.gz" "$YARN_CACHE_FOLDER"
|
||||
displayName: Pack cache
|
||||
- job: Linux
|
||||
pool:
|
||||
vmImage: ubuntu-16.04
|
||||
@ -110,25 +114,26 @@ jobs:
|
||||
inputs:
|
||||
versionSpec: $(node_version)
|
||||
displayName: Install Node.js
|
||||
- task: CacheBeta@0
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: cache | $(Agent.OS) | yarn.lock
|
||||
path: $(AZURE_CACHE_FOLDER)
|
||||
cacheHitVar: CACHE_RESTORED
|
||||
key: yarn | $(Agent.OS) | yarn.lock
|
||||
restoreKeys: |
|
||||
yarn | "$(Agent.OS)"
|
||||
yarn
|
||||
path: $(YARN_CACHE_FOLDER)
|
||||
displayName: Cache Yarn packages
|
||||
- bash: |
|
||||
mkdir -p "$YARN_CACHE_FOLDER"
|
||||
tar -xzf "$AZURE_CACHE_FOLDER/yarn-cache.tar.gz" -C /
|
||||
displayName: "Unpack cache"
|
||||
condition: eq(variables.CACHE_RESTORED, 'true')
|
||||
- script: make install-deps
|
||||
- script: make node_modules
|
||||
displayName: Install dependencies
|
||||
- script: make test-extensions
|
||||
displayName: Run In-tree Extension tests
|
||||
- script: make lint
|
||||
displayName: Lint
|
||||
- script: make build-npm
|
||||
displayName: Generate npm package
|
||||
- script: make -j2 build-extensions
|
||||
displayName: Build bundled extensions
|
||||
- script: make test
|
||||
displayName: Run tests
|
||||
- script: make test-extensions
|
||||
displayName: Run In-tree Extension tests
|
||||
- bash: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install libgconf-2-4 conntrack -y
|
||||
@ -160,7 +165,3 @@ jobs:
|
||||
condition: "and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))"
|
||||
env:
|
||||
NPM_TOKEN: $(NPM_TOKEN)
|
||||
- bash: |
|
||||
mkdir -p "$AZURE_CACHE_FOLDER"
|
||||
tar -czf "$AZURE_CACHE_FOLDER/yarn-cache.tar.gz" "$YARN_CACHE_FOLDER"
|
||||
displayName: Pack cache
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
ignorePatterns: ["src/extensions/npm/extensions/api.d.ts"],
|
||||
ignorePatterns: ["src/extensions/npm/extensions/dist/**/*"],
|
||||
overrides: [
|
||||
{
|
||||
files: [
|
||||
|
||||
17
.github/labeler-config.yml
vendored
@ -1,17 +0,0 @@
|
||||
---
|
||||
area/ui:
|
||||
- src/renderer/**/*
|
||||
area/test:
|
||||
- integration/**/*
|
||||
- __mocks__/**/*
|
||||
area/extension:
|
||||
- extensions/**/*
|
||||
- src/extensions/**/*
|
||||
area/documentation:
|
||||
- README.md
|
||||
- docs/**/*
|
||||
area/ci:
|
||||
- .github/workflows/**/*
|
||||
- .azure-pipelines.yml
|
||||
dependencies:
|
||||
- yarn.lock
|
||||
15
.github/workflows/labeler.yml
vendored
@ -1,15 +0,0 @@
|
||||
---
|
||||
name: "Pull Request Labeler"
|
||||
|
||||
on:
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v2
|
||||
if: github.repository == 'lensapp/lens'
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
configuration-path: .github/labeler-config.yml
|
||||
64
.github/workflows/main.yml
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
name: Publish docs via GitHub Pages
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
jobs:
|
||||
build:
|
||||
name: Deploy docs
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- name: Set up Python 3.7
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install git+https://${{ secrets.GH_TOKEN }}@github.com/lensapp/mkdocs-material-insiders.git
|
||||
pip install mike
|
||||
|
||||
|
||||
- name: Checkout Release from lens
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: git config
|
||||
run: |
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "GitHub Action"
|
||||
|
||||
- name: Using Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Generate Extensions API Reference using typedocs
|
||||
run: |
|
||||
yarn install
|
||||
yarn typedocs-extensions-api
|
||||
|
||||
- name: mkdocs deploy master
|
||||
if: contains(github.ref, 'refs/heads/master')
|
||||
run: |
|
||||
mike deploy --push master
|
||||
|
||||
- name: Get the release version
|
||||
if: contains(github.ref, 'refs/tags/v') # && !github.event.release.prerelease (generate pre-release docs until Lens 4.0.0 is GA, see #1408)
|
||||
id: get_version
|
||||
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
|
||||
|
||||
- name: mkdocs deploy new release
|
||||
if: contains(github.ref, 'refs/tags/v') # && !github.event.release.prerelease (generate pre-release docs until Lens 4.0.0 is GA, see #1408)
|
||||
run: |
|
||||
mike deploy --push --update-aliases ${{ steps.get_version.outputs.VERSION }} latest
|
||||
mike set-default --push ${{ steps.get_version.outputs.VERSION }}
|
||||
|
||||
38
.github/workflows/mkdocs-delete-version.yml
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
name: Delete Documentation Version
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Version string to be deleted (e.g."v0.0.1")'
|
||||
required: true
|
||||
jobs:
|
||||
build:
|
||||
name: Delete docs Version
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Python 3.7
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install git+https://${{ secrets.GH_TOKEN }}@github.com/lensapp/mkdocs-material-insiders.git
|
||||
pip install mike
|
||||
|
||||
- name: Checkout Release from lens
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: git config
|
||||
run: |
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "GitHub Action"
|
||||
|
||||
|
||||
- name: mkdocs delete version
|
||||
run: |
|
||||
mike delete --push ${{ github.event.inputs.version }}
|
||||
|
||||
38
.github/workflows/mkdocs-set-default-version.yml
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
name: Update Default Documentation Version
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Version string to be default (e.g."v0.0.1")'
|
||||
required: true
|
||||
jobs:
|
||||
build:
|
||||
name: Update default docs Version
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Python 3.7
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install git+https://${{ secrets.GH_TOKEN }}@github.com/lensapp/mkdocs-material-insiders.git
|
||||
pip install mike
|
||||
|
||||
- name: Checkout Release from lens
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: git config
|
||||
run: |
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "GitHub Action"
|
||||
|
||||
|
||||
- name: mkdocs update default version
|
||||
run: |
|
||||
mike set-default --push ${{ github.event.inputs.version }}
|
||||
|
||||
1
.gitignore
vendored
@ -15,3 +15,4 @@ src/extensions/*/*.d.ts
|
||||
types/extension-api.d.ts
|
||||
types/extension-renderer-api.d.ts
|
||||
extensions/*/dist
|
||||
docs/extensions/api
|
||||
|
||||
99
Makefile
@ -1,4 +1,7 @@
|
||||
EXTENSIONS_DIR = ./extensions
|
||||
extensions = $(foreach dir, $(wildcard $(EXTENSIONS_DIR)/*), ${dir})
|
||||
extension_node_modules = $(foreach dir, $(wildcard $(EXTENSIONS_DIR)/*), ${dir}/node_modules)
|
||||
extension_dists = $(foreach dir, $(wildcard $(EXTENSIONS_DIR)/*), ${dir}/dist)
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
DETECTED_OS := Windows
|
||||
@ -6,78 +9,126 @@ else
|
||||
DETECTED_OS := $(shell uname)
|
||||
endif
|
||||
|
||||
.PHONY: init dev build test clean
|
||||
|
||||
init: install-deps download-bins compile-dev
|
||||
echo "Init done"
|
||||
|
||||
download-bins:
|
||||
binaries/client:
|
||||
yarn download-bins
|
||||
|
||||
install-deps:
|
||||
yarn install --frozen-lockfile
|
||||
node_modules:
|
||||
yarn install --frozen-lockfile --verbose
|
||||
yarn check --verify-tree --integrity
|
||||
|
||||
static/build/LensDev.html:
|
||||
yarn compile:renderer
|
||||
|
||||
.PHONY: compile-dev
|
||||
compile-dev:
|
||||
yarn compile:main --cache
|
||||
yarn compile:renderer --cache
|
||||
|
||||
dev:
|
||||
ifeq ("$(wildcard static/build/main.js)","")
|
||||
make init
|
||||
endif
|
||||
.PHONY: dev
|
||||
dev: node_modules binaries/client build-extensions static/build/LensDev.html
|
||||
yarn dev
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
yarn lint
|
||||
|
||||
test: download-bins
|
||||
.PHONY: test
|
||||
test: binaries/client
|
||||
yarn test
|
||||
|
||||
.PHONY: integration-linux
|
||||
integration-linux: build-extension-types build-extensions
|
||||
yarn build:linux
|
||||
yarn integration
|
||||
|
||||
.PHONY: integration-mac
|
||||
integration-mac: build-extension-types build-extensions
|
||||
yarn build:mac
|
||||
yarn integration
|
||||
|
||||
.PHONY: integration-win
|
||||
integration-win: build-extension-types build-extensions
|
||||
yarn build:win
|
||||
yarn integration
|
||||
|
||||
.PHONY: test-app
|
||||
test-app:
|
||||
yarn test
|
||||
|
||||
build: install-deps download-bins build-extensions
|
||||
.PHONY: build
|
||||
build: node_modules binaries/client build-extensions
|
||||
ifeq "$(DETECTED_OS)" "Windows"
|
||||
yarn dist:win
|
||||
else
|
||||
yarn dist
|
||||
endif
|
||||
|
||||
build-extensions:
|
||||
$(foreach dir, $(wildcard $(EXTENSIONS_DIR)/*), $(MAKE) -C $(dir) build;)
|
||||
$(extension_node_modules):
|
||||
cd $(@:/node_modules=) && npm install --no-audit --no-fund
|
||||
|
||||
test-extensions:
|
||||
$(foreach dir, $(wildcard $(EXTENSIONS_DIR)/*), $(MAKE) -C $(dir) test;)
|
||||
$(extension_dists): src/extensions/npm/extensions/dist
|
||||
cd $(@:/dist=) && npm run build
|
||||
|
||||
build-npm: build-extension-types
|
||||
yarn npm:fix-package-version
|
||||
.PHONY: build-extensions
|
||||
build-extensions: $(extension_node_modules) $(extension_dists)
|
||||
|
||||
build-extension-types:
|
||||
.PHONY: test-extensions
|
||||
test-extensions: $(extension_node_modules)
|
||||
$(foreach dir, $(extensions), (cd $(dir) && npm run test || exit $?);)
|
||||
|
||||
.PHONY: copy-extension-themes
|
||||
copy-extension-themes:
|
||||
mkdir -p src/extensions/npm/extensions/dist/src/renderer/themes/
|
||||
cp $(wildcard src/renderer/themes/*.json) src/extensions/npm/extensions/dist/src/renderer/themes/
|
||||
|
||||
src/extensions/npm/extensions/__mocks__:
|
||||
cp -r __mocks__ src/extensions/npm/extensions/
|
||||
|
||||
src/extensions/npm/extensions/dist:
|
||||
yarn compile:extension-types
|
||||
|
||||
.PHONY: build-npm
|
||||
build-npm: build-extension-types copy-extension-themes src/extensions/npm/extensions/__mocks__
|
||||
yarn npm:fix-package-version
|
||||
|
||||
.PHONY: build-extension-types
|
||||
build-extension-types: src/extensions/npm/extensions/dist
|
||||
|
||||
.PHONY: publish-npm
|
||||
publish-npm: build-npm
|
||||
npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
|
||||
cd src/extensions/npm/extensions && npm publish --access=public
|
||||
|
||||
clean:
|
||||
.PHONY: clean-extensions
|
||||
clean-extensions:
|
||||
ifeq "$(DETECTED_OS)" "Windows"
|
||||
if exist binaries\client del /s /q binaries\client\*.*
|
||||
$(foreach dir, $(wildcard $(EXTENSIONS_DIR)/*), if exist $(dir)\dist del /s /q $(dir)\dist)
|
||||
$(foreach dir, $(wildcard $(EXTENSIONS_DIR)/*), if exist $(dir)\node_modules del /s /q $(dir)\node_modules)
|
||||
else
|
||||
$(foreach dir, $(wildcard $(EXTENSIONS_DIR)/*), rm -rf $(dir)/dist)
|
||||
$(foreach dir, $(wildcard $(EXTENSIONS_DIR)/*), rm -rf $(dir)/node_modules)
|
||||
endif
|
||||
|
||||
.PHONY: clean-npm
|
||||
clean-npm:
|
||||
ifeq "$(DETECTED_OS)" "Windows"
|
||||
if exist src\extensions\npm\extensions\dist del /s /q src\extensions\npm\extensions\dist
|
||||
if exist src\extensions\npm\extensions\__mocks__ del /s /q src\extensions\npm\extensions\__mocks__
|
||||
if exist src\extensions\npm\extensions\node_modules del /s /q src\extensions\npm\extensions\node_modules
|
||||
else
|
||||
rm -rf src/extensions/npm/extensions/dist
|
||||
rm -rf src/extensions/npm/extensions/__mocks__
|
||||
rm -rf src/extensions/npm/extensions/node_modules
|
||||
endif
|
||||
|
||||
.PHONY: clean
|
||||
clean: clean-npm clean-extensions
|
||||
ifeq "$(DETECTED_OS)" "Windows"
|
||||
if exist binaries\client del /s /q binaries\client
|
||||
if exist dist del /s /q dist\*.*
|
||||
if exist static\build del /s /q static\build\*.*
|
||||
else
|
||||
rm -rf binaries/client/*
|
||||
rm -rf binaries/client
|
||||
rm -rf dist/*
|
||||
rm -rf static/build/*
|
||||
endif
|
||||
|
||||
33
README.md
@ -4,20 +4,24 @@
|
||||
[](https://github.com/lensapp/lens/releases)
|
||||
[](https://join.slack.com/t/k8slens/shared_invite/enQtOTc5NjAyNjYyOTk4LWU1NDQ0ZGFkOWJkNTRhYTc2YjVmZDdkM2FkNGM5MjhiYTRhMDU2NDQ1MzIyMDA4ZGZlNmExOTc0N2JmY2M3ZGI)
|
||||
|
||||
Lens is the only IDE you’ll ever need to take control of your Kubernetes clusters. It is a standalone application for MacOS, Windows and Linux operating systems. It is open source and free.
|
||||
World’s most popular Kubernetes IDE provides a simplified, consistent entry point for developers, testers, integrators, and DevOps, to ship code faster at scale. Lens is the only IDE you’ll ever need to take control of your Kubernetes clusters. It is a standalone application for MacOS, Windows and Linux operating systems. Lens is an open source project and free!
|
||||
|
||||
[](https://youtu.be/04v2ODsmtIs)
|
||||
|
||||
## What makes Lens special?
|
||||
|
||||
* Amazing usability and end-user experience
|
||||
* Multi cluster management: support for hundreds of clusters
|
||||
* Unified, secure, multi-cluster management on any platform: support for hundreds of clusters
|
||||
* Standalone application: no need to install anything in-cluster
|
||||
* Lens installs anywhere, elimanting the need to wrangle credentials
|
||||
* Real-time cluster state visualization
|
||||
* Resource utilization charts and trends with history powered by built-in Prometheus
|
||||
* Terminal access to nodes and containers
|
||||
* Smart terminal access to nodes and containers
|
||||
* Clusters can be local (e.g. minikube) or external (e.g. EKS, GKE, AKS)
|
||||
* Performance optimized to handle massive clusters (tested with a cluster running 25k pods)
|
||||
* Full support for Kubernetes RBAC
|
||||
* RBAC security is preserved, as Lens uses the standard Kubernetes API
|
||||
* Lens Extensions are used to add custom visualizations and functionality to accelerate development workflows for all the technologies and services that integrate with Kubernetes
|
||||
* Helm package deployment: Browse and deploy Helm charts with one click-Install
|
||||
|
||||
## Installation
|
||||
|
||||
@ -32,7 +36,6 @@ brew cask install lens
|
||||
|
||||
> Prerequisites: Nodejs v12, make, yarn
|
||||
|
||||
* `make init` - initial compilation, installing deps, etc.
|
||||
* `make dev` - builds and starts the app
|
||||
* `make test` - run tests
|
||||
|
||||
@ -40,19 +43,31 @@ brew cask install lens
|
||||
|
||||
Allows for faster separate re-runs of some of the more involved processes:
|
||||
|
||||
1. `yarn dev:main` compiles electron's main process app part
|
||||
1. `yarn dev:renderer` compiles electron's renderer app part
|
||||
1. `yarn dev:extension-types` compile declaration types for `@k8slens/extensions`
|
||||
1. `yarn dev:main` compiles electron's main process app part
|
||||
1. `yarn dev:renderer` compiles electron's renderer app part
|
||||
1. `yarn dev:extension-types` compile declaration types for `@k8slens/extensions`
|
||||
1. `yarn dev-run` runs app in dev-mode and auto-restart when main process file has changed
|
||||
|
||||
## Development (documentation)
|
||||
|
||||
Run a local instance of `mkdocs serve` in a docker container for developing the Lens Documentation.
|
||||
|
||||
> Prerequisites: docker, yarn
|
||||
|
||||
* `yarn mkdocs-serve-local` - local build and serve of mkdocs with auto update enabled
|
||||
|
||||
Go to [localhost:8000](http://127.0.0.1:8000)
|
||||
|
||||
## Developer's ~~RTFM~~ recommended list:
|
||||
|
||||
- [TypeScript](https://www.typescriptlang.org/docs/home.html) (front-end/back-end)
|
||||
- [TypeScript](https://www.typescriptlang.org/docs/home.html) (front-end/back-end)
|
||||
- [ReactJS](https://reactjs.org/docs/getting-started.html) (front-end, ui)
|
||||
- [MobX](https://mobx.js.org/) (app-state-management, back-end/front-end)
|
||||
- [ElectronJS](https://www.electronjs.org/docs) (chrome/node)
|
||||
- [NodeJS](https://nodejs.org/dist/latest-v12.x/docs/api/) (api docs)
|
||||
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
Bug reports and pull requests are welcome on GitHub at https://github.com/lensapp/lens.
|
||||
1
docs/CNAME
Normal file
@ -0,0 +1 @@
|
||||
docs.k8slens.dev
|
||||
21
docs/README.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Overview
|
||||
|
||||
Lens is the most powerful Kubernetes IDE on the market. It is a standalone application, and it is available on macOS, Windows, and Linux. Some of the benefits of using Lens include:
|
||||
|
||||
* Confidence that your clusters are properly setup and configured.
|
||||
* Increased visibility, real time statistics, log streams, and hands-on troubleshooting capabilities.
|
||||
* The ability to work with your clusters quickly and easily, radically improving productivity and the speed of business.
|
||||
|
||||
Watch this introductory video to see Lens in action:
|
||||
|
||||
[](https://youtu.be/04v2ODsmtIs)
|
||||
|
||||
**Note:** Use CTRL+click (on Windows and Linux) or CMD+click (on MacOS) to open the above in a new tab
|
||||
|
||||
## Downloading Lens
|
||||
|
||||
[Download Lens](https://github.com/lensapp/lens/releases) for macOS, Windows, or Linux.
|
||||
|
||||
## Quick Start
|
||||
|
||||
Get up and running quickly by learning to [add clusters](clusters/adding-clusters.md).
|
||||
16
docs/clusters/adding-clusters.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Adding Clusters
|
||||
|
||||
Add clusters by clicking the **Add Cluster** button in the left-side menu.
|
||||
|
||||
1. Click the **Add Cluster** button (indicated with a '+' icon).
|
||||
2. Enter the path to your kubeconfig file. You'll need to have a kubeconfig file for the cluster you want to add. You can either browse for the path from the file system or or enter it directly.
|
||||
|
||||
Selected [cluster contexts](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#context) are added as a separate item in the left-side cluster menu to allow you to operate easily on multiple clusters and/or contexts.
|
||||
|
||||
**NOTE**: Any cluster that you added manually will not be merged into your kubeconfig file.
|
||||
|
||||

|
||||
|
||||
For more information on kubeconfig see [Kubernetes docs](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/).
|
||||
|
||||
To see your currently-enabled config with `kubectl`, enter `kubectl config view --minify --raw` in your terminal.
|
||||
BIN
docs/clusters/images/add-cluster.png
Normal file
|
After Width: | Height: | Size: 252 KiB |
BIN
docs/clusters/images/cluster-context-menu.png
Normal file
|
After Width: | Height: | Size: 284 KiB |
BIN
docs/clusters/images/cluster-settings-features.png
Normal file
|
After Width: | Height: | Size: 315 KiB |
BIN
docs/clusters/images/cluster-settings-general.png
Normal file
|
After Width: | Height: | Size: 311 KiB |
BIN
docs/clusters/images/cluster-settings-removal.png
Normal file
|
After Width: | Height: | Size: 338 KiB |
BIN
docs/clusters/images/cluster-settings-status.png
Normal file
|
After Width: | Height: | Size: 170 KiB |
BIN
docs/clusters/images/cluster-settings.png
Normal file
|
After Width: | Height: | Size: 262 KiB |
BIN
docs/clusters/images/remove-cluster.png
Normal file
|
After Width: | Height: | Size: 90 KiB |
12
docs/clusters/removing-clusters.md
Normal file
@ -0,0 +1,12 @@
|
||||
# Removing Clusters
|
||||
|
||||
Remove Lens clusters using the context menu that appears when you right-click the cluster in the left-side menu that you want to remove.
|
||||
|
||||
To remove a cluster from your cluster list:
|
||||
|
||||
1. Right-click the name of the cluster in the left-side menu that you want to remove.
|
||||
2. Click **Remove**.
|
||||
|
||||
**NOTE**: This will only remove the cluster from your Lens cluster list. It will not affect your actual Kubernetes cluster or its configuration.
|
||||
|
||||

|
||||
75
docs/clusters/settings.md
Normal file
@ -0,0 +1,75 @@
|
||||
# Settings
|
||||
|
||||
It is easy to configure Lens Clusters to your liking through its various settings.
|
||||
|
||||
1. Right-click the name of the cluster in the left-side menu that you want to open the settings for.
|
||||
2. Click **Settings**.
|
||||
|
||||

|
||||
|
||||
## Status
|
||||
|
||||
Overview of the cluster status
|
||||
|
||||
### Cluster Status
|
||||
|
||||
Cluster status information including the detected distribution, kernel version, API endpoint, and online status
|
||||
|
||||

|
||||
|
||||
## General
|
||||
|
||||
General cluster settings
|
||||
|
||||
### Cluster Name
|
||||
|
||||
The cluster name is inheritated by default from the kubeconfig file. Change the cluster name to another value by updating it here. Note that doing so does not update your kubeconfig file.
|
||||
|
||||
### Workspace
|
||||
|
||||
This is the Lens workspace that the cluster is associated with. Change workspaces by selecting a different workspace from the dropdown menu. Create a new workspace by clicking **workspace** in "Define cluster workspace" above the dropdown menu. This option will take you the workspaces editor. Create a new workspace and then navigate back to cluster settings.
|
||||
|
||||
### Cluster Icon
|
||||
|
||||
Lens randomly generates an icon to associate with each newly-created cluster. Use this setting to choose your own icon.
|
||||
|
||||
### HTTP Proxy
|
||||
|
||||
Some users will need to define an HTTP proxy for communicating with the Kubernetes API. Use this setting to do so.
|
||||
|
||||
### Prometheus
|
||||
|
||||
Lens can be configured to query a Prometheus server installed in the cluster. Select a query format by choosing either to auto-detect or from the following configurations:
|
||||
|
||||
* Lens
|
||||
* Helm Operator
|
||||
* Prometheus Operator
|
||||
* Stacklight
|
||||
|
||||
To learn more about custom Prometheus configurations, please refer to this [guide](https://github.com/lensapp/lens/blob/master/troubleshooting/custom-prometheus.md).
|
||||
|
||||
### Working Directory
|
||||
|
||||
Use this field to set the terminal working directory. The default is `$HOME`.
|
||||
|
||||

|
||||
|
||||
## Features
|
||||
|
||||
Additional Lens features that can be installed by the user
|
||||
|
||||
### Metrics
|
||||
|
||||
Enable timeseries data visualization (Prometheus stack) for your cluster. Install this only if you don't have existing Prometheus stack installed.
|
||||
|
||||
### User Mode
|
||||
|
||||
User Mode feature enables non-admin users to see namespaces they have access to. This is achieved by configuring RBAC rules so that every authenticated user is granted to list namespaces.
|
||||
|
||||

|
||||
|
||||
## Removal
|
||||
|
||||
Use this setting to remove the current cluster.
|
||||
|
||||

|
||||
17
docs/contributing/README.md
Normal file
@ -0,0 +1,17 @@
|
||||
# Contributing
|
||||
|
||||
There are multiple ways you can contribute to Lens. Even if you are not a developer, you can still contribute. We are always looking for assistance with creating or updating documentation, testing the application, reporting, and troubleshooting issues.
|
||||
|
||||
Here are some ways you can contribute!
|
||||
|
||||
* [Development](./development.md) – Help make Lens better.
|
||||
* [Maintaining the Project](./maintainers.md) – Become a community maintainer and help us maintain the project.
|
||||
* [Extension Development](../extensions) – Add integrations via Lens Extensions.
|
||||
* [Documentation](./documentation.md) – Help improve Lens documentation.
|
||||
* [Promotion](./promotion.md) – Show your support, be an ambassador to Lens, write blogs, and make videos!
|
||||
|
||||
If you are an influencer, blogger, or journalist, feel free to [spread the word](./promotion.md)!
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project adheres to the [Contributor Covenant](https://www.contributor-covenant.org/) code of conduct. By participating and contributing to Lens, you are expected to uphold this code. Please report unacceptable behaviour to info@k8slens.dev.
|
||||
3
docs/contributing/development.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Development
|
||||
|
||||
TBD
|
||||
22
docs/contributing/documentation.md
Normal file
@ -0,0 +1,22 @@
|
||||
# Documentation
|
||||
|
||||
We are glad to see you're interested in contributing to the Lens documentation. If this is the first Open Source project you've contributed to, we strongly suggest reading GitHub's excellent guide: [How to Contribute to Open Source](https://opensource.guide/how-to-contribute).
|
||||
|
||||
## Finding Documentation Issues to Work On
|
||||
|
||||
You can find a list of open documentation-related issues [here](https://github.com/lensapp/lens/issues?q=is%3Aopen+is%3Aissue+label%3Aarea%2Fdocumentation). When you find something you would like to work on:
|
||||
|
||||
1. Express your interest to start working on an issue via comments.
|
||||
2. One of the maintainers will assign the issue for you.
|
||||
3. You can start working on the issue. When you're done, simply submit a pull request.
|
||||
|
||||
## Requirements for Documentation Pull Requests
|
||||
|
||||
When you create a new pull request, we expect some requirements to be met.
|
||||
|
||||
* Follow this naming convention for Pull Requests:
|
||||
* When adding new documentation, add `New Documentation:` before the title. E.g. `New Documentation: Getting Started`
|
||||
* When fixing documentation, add `Fix Documentation:` before the title. E.g. `Fix Documentation: Getting Started`
|
||||
* When updating documentation, add `Update Documentation:` before the title. E.g. `Update Documentation: Getting Started`
|
||||
* If your Pull Request closes an issue, you must write `Closes #ISSUE_NUMBER` where the ISSUE_NUMBER is the number in the end of the link url or the relevent issue. This will link your pull request to the issue, and when it is merged, the issue will close.
|
||||
* For each pull request made, we run tests to check if there are any broken links, the markdown formatting is valid, and the linter is passing.
|
||||
17
docs/contributing/maintainers.md
Normal file
@ -0,0 +1,17 @@
|
||||
# Maintainers
|
||||
|
||||
We are looking for community maintainers for the Lens project. Maintainers will be added to a special team with write permissions. These permissions consist of opening, closing, tagging, and editing issues and pull requests, as well as creating and deleting non-protected branches.
|
||||
|
||||
The responsibilities of a community maintainer are listed below.
|
||||
|
||||
## Issues Triage
|
||||
|
||||
* **Labeling Issues:** Label issues accordingly.
|
||||
* **Finding Duplicates:** Finding and closing duplicate issues.
|
||||
* **Doing First Level Contact:** Getting more information on the issues (like version number or asking for clarification) if needed.
|
||||
* **Closing Irrelevant Issues:** Closing issues that are determined irrelevant, no longer needed, not relevant to the project and/or don't follow the issues guidelines.
|
||||
|
||||
## Help with Contributions
|
||||
|
||||
* **Help Manage Pull Requests:** Help the author of the pull request with any problems.
|
||||
* **Contributing:** Create pull requests to help maintain and drive the project forward.
|
||||
27
docs/contributing/promotion.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Promotion
|
||||
|
||||
Help promote Lens! If you are not a developer (or even if you are), you can still contribute to the project – a lot – by helping us to promote it. As we are a free and open source project, the community is our most important asset. Here are some ways that you can help the project continue to grow.
|
||||
|
||||
## Follow, Like, Recommend, Favorite, Vote and Star Us
|
||||
|
||||
There are many sites where you can vote, recommend, favorite, and star us.
|
||||
|
||||
* [Twitter](https://twitter.com/k8slens) - Like, comment and retweet our posts, and follow us on Twitter.
|
||||
* [Medium](https://medium.com/k8slens) - Give claps to our articles and follow us on Medium.
|
||||
* [GitHub](https://github.com/lensapp/lens) - Become a stargazer on GitHub.
|
||||
* [StackShare](https://stackshare.io/lens) - Indicate you are using Lens and follow us on StackShare.
|
||||
* [Reddit](https://www.reddit.com/search/?q=lens%20kubernetes&sort=new) - Upvote and be a Lens ambassador by participating in relevant discussions on Reddit.
|
||||
* [Hacker News](https://hn.algolia.com/?dateRange=all&page=0&prefix=false&query=lens%20kubernetes&sort=byDate&type=story) - Upvote and be a Lens ambassador by participating in relevant discussions on Hacker News.
|
||||
|
||||
## Write Blogs or Make Videos About Us
|
||||
|
||||
Here are some nice blog posts and videos about our project for you to get some inspiration:
|
||||
|
||||
* [Onboard AWS EKS Cluster on Lens(Kubernetes IDE)](https://dev.to/himwad05/onboard-aws-eks-cluster-on-lens-kubernetes-ide-492l)
|
||||
* [Using Lens to Manage All Your Kubernetes Cluster](https://medium.com/@magicmagnate/using-lens-to-manage-all-your-kubernetes-cluster-c1ef88fdb476)
|
||||
* [Kontena Lens - Beautiful Kubernetes UI](https://www.youtube.com/watch?v=YGgaiGdYfdI)
|
||||
* [Gerenciando Kubernetes com Lens e Octant](https://www.youtube.com/watch?v=h9ZqDelJLQQ)
|
||||
* [Walkthrough of Kubernetes IDE - Lens](https://www.youtube.com/watch?v=602aHZSdEfY)
|
||||
* [LENS - Interfaz Gráfica para Kubernetes en 1 PASO.](https://www.youtube.com/watch?v=DFMKcR4BqwM)
|
||||
|
||||
Psst... If you have created some content around Lens, let us know!
|
||||
BIN
docs/custom_theme/img/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
12
docs/custom_theme/main.html
Normal file
@ -0,0 +1,12 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block analytics %}
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-90E1JB4HW4"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-90E1JB4HW4');
|
||||
</script>
|
||||
{% endblock %}
|
||||
43
docs/extensions/README.md
Normal file
@ -0,0 +1,43 @@
|
||||
# Lens Extension API
|
||||
|
||||
Customize and enhance the Lens experience with the Lens Extension API. Use the extension API to create menus or page content. The same extension API was used to create many of Lens's core features.
|
||||
|
||||
This documentation describes:
|
||||
|
||||
* How to build, run, test, and publish an extension.
|
||||
* How to take full advantage of the Lens Extension API.
|
||||
* Where to find [guides](guides/README.md) and [code samples](https://github.com/lensapp/lens-extension-samples) to help get you started.
|
||||
|
||||
## What Extensions Can Do
|
||||
|
||||
Here are some examples of what you can achieve with the Extension API:
|
||||
|
||||
* Add custom components & views in the UI - Extending the Lens Workbench
|
||||
|
||||
For an overview of the Lens Extension API, refer to the [Common Capabilities](capabilities/common-capabilities.md) page. [Extension Guides Overview](guides/overview.md) also includes a list of code samples and guides that illustrate various ways of using the Lens Extension API.
|
||||
|
||||
## How to Build Extensions
|
||||
|
||||
Here is what each section of the Lens Extension API docs can help you with:
|
||||
|
||||
* **Getting Started** teaches fundamental concepts for building extensions with the Hello World sample.
|
||||
* **Extension Capabilities** dissects Lens's Extension API into smaller categories and points you to more detailed topics.
|
||||
* **Extension Guides** includes guides and code samples that explain specific usages of Lens Extension API.
|
||||
* **Testing and Publishing** includes in-depth guides on various extension development topics, such as testing and publishing extensions.
|
||||
* **API Reference** contains exhaustive references for the Lens Extension API, Contribution Points, and many other topics.
|
||||
|
||||
## What's New
|
||||
|
||||
Just like Lens itself, the extension API updates on a monthly cadence, rolling out new features with every release.
|
||||
|
||||
Keep up with Lens and the Lens Extension API by reviewing the [release notes](https://github.com/lensapp/lens/releases).
|
||||
|
||||
## Looking for Help
|
||||
|
||||
If you have questions for extension development, try asking on the [Lens Dev Slack](http://k8slens.slack.com/). It's a public chatroom for Lens developers, where Lens team members chime in from time to time.
|
||||
|
||||
To provide feedback on the documentation or issues with the Lens Extension API, create new issues at [lensapp/lens](https://github.com/lensapp/lens/issues). Please use the labels `area/documentation` and/or `area/extension`.
|
||||
|
||||
## Downloading Lens
|
||||
|
||||
[Download Lens](https://github.com/lensapp/lens/releases) for macOS, Windows, or Linux.
|
||||
0
docs/extensions/capabilities/README.md
Normal file
130
docs/extensions/capabilities/color-reference.md
Normal file
@ -0,0 +1,130 @@
|
||||
# Theme Color Reference
|
||||
You can use theme-based CSS Variables to style an extension according to the active theme.
|
||||
|
||||
## Base Colors
|
||||
- `--blue`: blue color.
|
||||
- `--magenta`: magenta color.
|
||||
- `--golden`: gold/yellow color.
|
||||
- `--halfGray`: gray with some apacity applied.
|
||||
- `--primary`: Lens brand (blue) color.
|
||||
- `--colorSuccess`: successfull operations color.
|
||||
- `--colorOk`: successfull operations (bright version) color.
|
||||
- `--colorInfo`: informational, in-progress color.
|
||||
- `--colorError`: critical error color.
|
||||
- `--colorSoftError`: error color.
|
||||
- `--colorWarning`: warning color.
|
||||
- `--colorVague`: soft gray color for notices, hints etc.
|
||||
- `--colorTerminated`: terminated, closed, stale color.
|
||||
- `--boxShadow`: semi-transparent box-shadow color.
|
||||
|
||||
## Text Colors
|
||||
- `--textColorPrimary`: foreground text color.
|
||||
- `--textColorSecondary`: foreground text color for different paragraps, parts of text.
|
||||
- `--textColorAccent`: foreground text color to highlight its parts.
|
||||
|
||||
## Border Colors
|
||||
- `--borderColor`: border color.
|
||||
- `--borderFaintColor`: fainted (lighter or darker, which depends on the theme) border color.
|
||||
|
||||
## Layout Colors
|
||||
- `--mainBackground`: main background color for the app.
|
||||
- `--contentColor`: background color for panels contains some data.
|
||||
- `--layoutBackground`: background color for layout parts.
|
||||
- `--layoutTabsBackground`: background color for general tabs.
|
||||
- `--layoutTabsActiveColor`: foreground color for general tabs.
|
||||
- `--layoutTabsLineColor`: background color for lines under general tabs.
|
||||
|
||||
## Sidebar Colors
|
||||
- `--sidebarLogoBackground`: background color behind logo in sidebar.
|
||||
- `--sidebarActiveColor`: foreground color for active menu items in sidebar.
|
||||
- `--sidebarSubmenuActiveColor`: foreground color for active submenu items in sidebar.
|
||||
- `--sidebarBackground`: background color for sidebar.
|
||||
|
||||
## Button Colors
|
||||
- `--buttonPrimaryBackground`: button background color for primary actions.
|
||||
- `--buttonDefaultBackground`: default button background color.
|
||||
- `--buttonAccentBackground`: accent button background color.
|
||||
- `--buttonDisabledBackground`: disabled button background color.
|
||||
|
||||
## Table Colors
|
||||
- `--tableBgcStripe`: background color for odd rows in table.
|
||||
- `--tableBgcSelected`: background color for selected row in table.
|
||||
- `--tableHeaderBackground`: background color for table header.
|
||||
- `--tableHeaderBorderWidth`: border width under table header.
|
||||
- `--tableHeaderBorderColor`: border color for line under table header.
|
||||
- `--tableHeaderColor`: foreground color for table header.
|
||||
- `--tableSelectedRowColor`: foreground color for selected row in table.
|
||||
|
||||
## Dock Colors
|
||||
- `--dockHeadBackground`: background color for dock's header.
|
||||
- `--dockInfoBackground`: background color for dock's info panel.
|
||||
- `--dockInfoBorderColor`: border color for dock's info panel.
|
||||
|
||||
## Helm Chart Colors
|
||||
- `--helmLogoBackground`: background color for chart logo.
|
||||
- `--helmImgBackground`: background color for chart image.
|
||||
- `--helmStableRepo`: background color for stable repo.
|
||||
- `--helmIncubatorRepo`: background color for incubator repo.
|
||||
- `--helmDescriptionHr`: Helm chart description separator line color.
|
||||
- `--helmDescriptionBlockqouteColor`: Helm chart description blockquote color.
|
||||
- `--helmDescriptionBlockqouteBorder`: Helm chart description blockquote border color.
|
||||
- `--helmDescriptionBlockquoteBackground`: Helm chart description blockquote background color.
|
||||
- `--helmDescriptionHeaders`: Helm chart description headers color.
|
||||
- `--helmDescriptionH6`: Helm chart description header foreground color.
|
||||
- `--helmDescriptionTdBorder`: Helm chart description table cell border color.
|
||||
- `--helmDescriptionTrBackground`: Helm chart description table row background color.
|
||||
- `--helmDescriptionCodeBackground`: Helm chart description code background color.
|
||||
- `--helmDescriptionPreBackground`: Helm chart description pre background color.
|
||||
- `--helmDescriptionPreColor`: Helm chart description pre foreground color.
|
||||
|
||||
## Terminal Colors
|
||||
- `--terminalBackground`: Terminal background color.
|
||||
- `--terminalForeground`: Terminal foreground color.
|
||||
- `--terminalCursor`: Terminal cursor color.
|
||||
- `--terminalCursorAccent`: Terminal cursor accent color.
|
||||
- `--terminalSelection`: Terminal selection background color.
|
||||
- `--terminalBlack`: Terminal black color.
|
||||
- `--terminalRed`: Terminal red color.
|
||||
- `--terminalGreen`: Terminal green color.
|
||||
- `--terminalYellow`: Terminal yellow color.
|
||||
- `--terminalBlue`: Terminal blue color.
|
||||
- `--terminalMagenta`: Terminal magenta color.
|
||||
- `--terminalCyan`: Terminal cyan color.
|
||||
- `--terminalWhite`: Terminal white color.
|
||||
- `--terminalBrightBlack`: Terminal bright black color.
|
||||
- `--terminalBrightRed`: Terminal bright red color.
|
||||
- `--terminalBrightGreen`: Terminal bright green color.
|
||||
- `--terminalBrightYellow`: Terminal bright yellow color.
|
||||
- `--terminalBrightBlue`: Terminal bright blue color.
|
||||
- `--terminalBrightMagenta`: Terminal bright magenta color.
|
||||
- `--terminalBrightCyan`: Terminal bright cyan color.
|
||||
- `--terminalBrightWhite`: Terminal bright white color.
|
||||
|
||||
## Dialog Colors
|
||||
- `--dialogHeaderBackground`: background color for dialog header.
|
||||
- `--dialogFooterBackground`: background color for dialog footer.
|
||||
|
||||
## Detail Panel (Drawer) Colors
|
||||
- `--drawerTitleText`: drawer title foreground color.
|
||||
- `--drawerSubtitleBackground`: drawer subtitle foreground color.
|
||||
- `--drawerItemNameColor`: foreground color for item name in drawer.
|
||||
- `--drawerItemValueColor`: foreground color for item value in drawer.
|
||||
|
||||
## Misc Colors
|
||||
- `--logsBackground`: background color for pod logs.
|
||||
- `--clusterMenuBackground`: background color for cluster menu.
|
||||
- `--clusterMenuBorderColor`: border color for cluster menu.
|
||||
- `--clusterSettingsBackground`: background color for cluster settings.
|
||||
- `--addClusterIconColor`: add cluster button background color.
|
||||
- `--iconActiveColor`: active cluster icon foreground color.
|
||||
- `--iconActiveBackground`: active cluster icon background color.
|
||||
- `--filterAreaBackground`: page filter area (where selected namespaces are lister) background color.
|
||||
- `--chartStripesColor`: bar chart zebra stripes background color.
|
||||
- `--chartCapacityColor`: background color for capacity values in bar charts.
|
||||
- `--pieChartDefaultColor`: default background color for pie chart values.
|
||||
- `--selectOptionHoveredColor`: foregrond color for selected element in dropdown list.
|
||||
- `--lineProgressBackground`: background color for progress line.
|
||||
- `--radioActiveBackground`: background color for active radio buttons.
|
||||
- `--menuActiveBackground`: background color for active menu items.
|
||||
|
||||
In most cases you would only need base, text and some of the layout colors.
|
||||
274
docs/extensions/capabilities/common-capabilities.md
Normal file
@ -0,0 +1,274 @@
|
||||
# Common Capabilities
|
||||
|
||||
Here we will discuss common and important building blocks for your extensions, and explain how you can use them. Almost all extensions use some of these functionalities.
|
||||
|
||||
## Main Extension
|
||||
|
||||
The main extension runs in the background. It adds app menu items to the Lens UI. In order to see logs from this extension, you need to start Lens from the command line.
|
||||
|
||||
### Activate
|
||||
|
||||
This extension can register a custom callback that is executed when an extension is activated (started).
|
||||
|
||||
``` javascript
|
||||
import { LensMainExtension } from "@k8slens/extensions"
|
||||
|
||||
export default class ExampleMainExtension extends LensMainExtension {
|
||||
async onActivate() {
|
||||
console.log("hello world")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Deactivate
|
||||
|
||||
This extension can register a custom callback that is executed when an extension is deactivated (stopped).
|
||||
|
||||
``` javascript
|
||||
import { LensMainExtension } from "@k8slens/extensions"
|
||||
|
||||
export default class ExampleMainExtension extends LensMainExtension {
|
||||
async onDeactivate() {
|
||||
console.log("bye bye")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### App Menus
|
||||
|
||||
This extension can register custom app menus that will be displayed on OS native menus.
|
||||
|
||||
Example:
|
||||
|
||||
``` typescript
|
||||
import { LensMainExtension, windowManager } from "@k8slens/extensions"
|
||||
|
||||
export default class ExampleMainExtension extends LensMainExtension {
|
||||
appMenus = [
|
||||
{
|
||||
parentId: "help",
|
||||
label: "Example item",
|
||||
click() {
|
||||
windowManager.navigate("https://k8slens.dev");
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Renderer Extension
|
||||
|
||||
The renderer extension runs in a browser context, and is visible in Lens's main window. In order to see logs from this extension you need to check them via **View** > **Toggle Developer Tools** > **Console**.
|
||||
|
||||
### Activate
|
||||
|
||||
This extension can register a custom callback that is executed when an extension is activated (started).
|
||||
|
||||
``` javascript
|
||||
import { LensRendererExtension } from "@k8slens/extensions"
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
async onActivate() {
|
||||
console.log("hello world")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Deactivate
|
||||
|
||||
This extension can register a custom callback that is executed when an extension is deactivated (stopped).
|
||||
|
||||
``` javascript
|
||||
import { LensRendererExtension } from "@k8slens/extensions"
|
||||
|
||||
export default class ExampleMainExtension extends LensRendererExtension {
|
||||
async onDeactivate() {
|
||||
console.log("bye bye")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Global Pages
|
||||
|
||||
This extension can register custom global pages (views) to Lens's main window. The global page is a full-screen page that hides all other content from a window.
|
||||
|
||||
``` typescript
|
||||
import React from "react"
|
||||
import { Component, LensRendererExtension } from "@k8slens/extensions"
|
||||
import { ExamplePage } from "./src/example-page"
|
||||
|
||||
export default class ExampleRendererExtension extends LensRendererExtension {
|
||||
globalPages = [
|
||||
{
|
||||
id: "example",
|
||||
routePath: "/example",
|
||||
components: {
|
||||
Page: ExamplePage,
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
globalPageMenus = [
|
||||
{
|
||||
title: "Example page", // used in icon's tooltip
|
||||
target: { pageId: "example" }
|
||||
components: {
|
||||
Icon: () => <Component.Icon material="arrow"/>,
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### App Preferences
|
||||
|
||||
This extension can register custom app preferences. It is responsible for storing a state for custom preferences.
|
||||
|
||||
``` typescript
|
||||
import React from "react"
|
||||
import { LensRendererExtension } from "@k8slens/extensions"
|
||||
import { myCustomPreferencesStore } from "./src/my-custom-preferences-store"
|
||||
import { MyCustomPreferenceHint, MyCustomPreferenceInput } from "./src/my-custom-preference"
|
||||
|
||||
|
||||
export default class ExampleRendererExtension extends LensRendererExtension {
|
||||
appPreferences = [
|
||||
{
|
||||
title: "My Custom Preference",
|
||||
components: {
|
||||
Hint: () => <MyCustomPreferenceHint/>,
|
||||
Input: () => <MyCustomPreferenceInput store={myCustomPreferencesStore}/>
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Cluster Pages
|
||||
|
||||
This extension can register custom cluster pages. These pages are visible in a cluster menu when a cluster is opened.
|
||||
|
||||
``` typescript
|
||||
import React from "react"
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { ExampleIcon, ExamplePage } from "./src/page"
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
clusterPages = [
|
||||
{
|
||||
routePath: "/extension-example", // optional
|
||||
exact: true, // optional
|
||||
components: {
|
||||
Page: () => <ExamplePage extension={this}/>,
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
clusterPageMenus = [
|
||||
{
|
||||
url: "/extension-example", // optional
|
||||
title: "Example Extension",
|
||||
components: {
|
||||
Icon: ExampleIcon,
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Cluster Features
|
||||
|
||||
This extension can register installable features for a cluster. These features are visible in the "Cluster Settings" page.
|
||||
|
||||
``` typescript
|
||||
import React from "react"
|
||||
import { LensRendererExtension } from "@k8slens/extensions"
|
||||
import { MyCustomFeature } from "./src/my-custom-feature"
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
clusterFeatures = [
|
||||
{
|
||||
title: "My Custom Feature",
|
||||
components: {
|
||||
Description: () => {
|
||||
return (
|
||||
<span>
|
||||
Just an example.
|
||||
</span>
|
||||
)
|
||||
}
|
||||
},
|
||||
feature: new MyCustomFeature()
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Status Bar Items
|
||||
|
||||
This extension can register custom icons and text to a status bar area.
|
||||
|
||||
``` typescript
|
||||
import React from "react";
|
||||
import { Component, LensRendererExtension, Navigation } from "@k8slens/extensions";
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
statusBarItems = [
|
||||
{
|
||||
item: (
|
||||
<div className="flex align-center gaps hover-highlight" onClick={() => this.navigate("/example-page")} >
|
||||
<Component.Icon material="favorite" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Kubernetes Object Menu Items
|
||||
|
||||
This extension can register custom menu items (actions) for specified Kubernetes kinds/apiVersions.
|
||||
|
||||
``` typescript
|
||||
import React from "react"
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { CustomMenuItem, CustomMenuItemProps } from "./src/custom-menu-item"
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
kubeObjectMenuItems = [
|
||||
{
|
||||
kind: "Node",
|
||||
apiVersions: ["v1"],
|
||||
components: {
|
||||
MenuItem: (props: CustomMenuItemProps) => <CustomMenuItem {...props} />
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Kubernetes Object Details
|
||||
|
||||
This extension can register custom details (content) for specified Kubernetes kinds/apiVersions.
|
||||
|
||||
``` typescript
|
||||
import React from "react"
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { CustomKindDetails, CustomKindDetailsProps } from "./src/custom-kind-details"
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
kubeObjectDetailItems = [
|
||||
{
|
||||
kind: "CustomKind",
|
||||
apiVersions: ["custom.acme.org/v1"],
|
||||
components: {
|
||||
Details: (props: CustomKindDetailsProps) => <CustomKindDetails {...props} />
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
BIN
docs/extensions/capabilities/images/css-vars-in-devtools.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
docs/extensions/capabilities/images/theme-selector.png
Normal file
|
After Width: | Height: | Size: 408 KiB |
150
docs/extensions/capabilities/styling.md
Normal file
@ -0,0 +1,150 @@
|
||||
# Styling an Extension
|
||||
|
||||
Lens provides a set of global styles and UI components that can be used by any extension to preserve the look and feel of the application.
|
||||
|
||||
## Layout
|
||||
|
||||
For layout tasks, Lens uses the [flex.box](https://www.npmjs.com/package/flex.box) library which provides helpful class names to specify some of the [flexbox](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox) properties. For example, consider the following HTML and its associated CSS properties:
|
||||
|
||||
```html
|
||||
<div className="flex column align-center"></div>
|
||||
```
|
||||
|
||||
```css
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
```
|
||||
|
||||
However, you are free to use any styling technique or framework you like, including [Emotion](https://github.com/emotion-js/emotion) or even plain CSS.
|
||||
|
||||
### Layout Variables
|
||||
|
||||
There is a set of CSS variables available for for basic layout needs. They are located inside `:root` and are defined in [app.scss](https://github.com/lensapp/lens/blob/master/src/renderer/components/app.scss):
|
||||
|
||||
```css
|
||||
--unit: 8px;
|
||||
--padding: var(--unit);
|
||||
--margin: var(--unit);
|
||||
--border-radius: 3px;
|
||||
```
|
||||
|
||||
These variables are intended to set consistent margins and paddings across components. For example:
|
||||
|
||||
```css
|
||||
.status {
|
||||
padding-left: calc(var(--padding) * 2);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
```
|
||||
|
||||
## Themes
|
||||
|
||||
Lens uses two built-in themes defined in [the themes directory](https://github.com/lensapp/lens/tree/master/src/renderer/themes) – one light and one dark.
|
||||
|
||||
### Theme Variables
|
||||
|
||||
When Lens is loaded, it transforms the selected theme's `json` file into a list of [CSS Custom Properties (CSS Variables)](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties). This list then gets injected into the `:root` element so that any of the down-level components can use them.
|
||||

|
||||
|
||||
When the user changes the theme, the above process is repeated, and new CSS variables appear, replacing the previous ones.
|
||||
|
||||
If you want to preserve Lens's native look and feel, with respect to the lightness or darkness of your extension, you can use the provided variables and built-in Lens components such as `Button`, `Select`, `Table`, and so on.
|
||||
|
||||
There is a set of CSS variables available for extensions to use for theming. They are all located inside `:root` and are defined in [app.scss](https://github.com/lensapp/lens/blob/master/src/renderer/components/app.scss):
|
||||
|
||||
```css
|
||||
--font-main: 'Roboto', 'Helvetica', 'Arial', sans-serif;
|
||||
--font-monospace: Lucida Console, Monaco, Consolas, monospace;
|
||||
--font-size-small: calc(1.5 * var(--unit));
|
||||
--font-size: calc(1.75 * var(--unit));
|
||||
--font-size-big: calc(2 * var(--unit));
|
||||
--font-weight-thin: 300;
|
||||
--font-weight-normal: 400;
|
||||
--font-weight-bold: 500;
|
||||
```
|
||||
|
||||
as well as in [the theme modules](https://github.com/lensapp/lens/tree/master/src/renderer/themes):
|
||||
|
||||
```
|
||||
--blue: #3d90ce;
|
||||
--magenta: #c93dce;
|
||||
--golden: #ffc63d;
|
||||
--halfGray: #87909c80;
|
||||
--primary: #3d90ce;
|
||||
--textColorPrimary: #555555;
|
||||
--textColorSecondary: #51575d;
|
||||
--textColorAccent: #333333;
|
||||
--borderColor: #c9cfd3;
|
||||
--borderFaintColor: #dfdfdf;
|
||||
--mainBackground: #f1f1f1;
|
||||
--contentColor: #ffffff;
|
||||
--layoutBackground: #e8e8e8;
|
||||
--layoutTabsBackground: #f8f8f8;
|
||||
--layoutTabsActiveColor: #333333;
|
||||
--layoutTabsLineColor: #87909c80;
|
||||
...
|
||||
```
|
||||
|
||||
These variables can be used in the following form: `var(--magenta)`. For example:
|
||||
|
||||
```css
|
||||
.status {
|
||||
font-size: var(--font-size-small);
|
||||
background-color: var(--colorSuccess);
|
||||
}
|
||||
```
|
||||
|
||||
A complete list of themable colors can be found in the [Color Reference](../color-reference).
|
||||
|
||||
### Theme Switching
|
||||
|
||||
When the light theme is active, the `<body>` element gets a "theme-light" class, or: `<body class="theme-light">`. If the class isn't there, the theme defaults to dark. The active theme can be changed in the **Preferences** page:
|
||||

|
||||
|
||||
Currently, there is no prescribed way of detecting changes to the theme in JavaScript. [This issue](https://github.com/lensapp/lens/issues/1336) has been raised to resolve this problem. In the meantime, you can use a [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) in order to observe the `<body>` element's `class` attribute in order to see if the "theme-light" class gets added to it:
|
||||
|
||||
```javascript
|
||||
...
|
||||
useEffect(function () {
|
||||
const observer = new MutationObserver(function (mutations: MutationRecord[]) {
|
||||
mutations.forEach((mutation: MutationRecord) => {
|
||||
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
|
||||
if ((mutation.target as HTMLElement).classList.contains('theme-light')) {
|
||||
// theme is LIGHT
|
||||
} else {
|
||||
// theme is DARK
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
observer.observe(document.body, {
|
||||
attributes: true,
|
||||
attributeFilter: ['class'],
|
||||
});
|
||||
|
||||
return function () {
|
||||
observer.disconnect();
|
||||
};
|
||||
}, []); // run once on mount
|
||||
...
|
||||
```
|
||||
|
||||
## Injected Styles
|
||||
|
||||
Every extension is affected by the list of default global styles defined in [app.scss](https://github.com/lensapp/lens/blob/master/src/renderer/components/app.scss). These are basic browser resets and element styles, including setting the `box-sizing` property for every element, default text and background colors, default font sizes, basic heading formatting, and so on.
|
||||
|
||||
Extensions may overwrite these defaults if needed. They have low CSS specificity, so overriding them should be fairly easy.
|
||||
|
||||
## CSS-in-JS
|
||||
|
||||
If an extension uses a system like `Emotion` to work with styles, it can use CSS variables as follows:
|
||||
|
||||
```javascript
|
||||
const Container = styled.div(() => ({
|
||||
backgroundColor: 'var(--mainBackground)'
|
||||
}));
|
||||
```
|
||||
97
docs/extensions/get-started/anatomy.md
Normal file
@ -0,0 +1,97 @@
|
||||
# Extension Anatomy
|
||||
|
||||
In the [previous section](your-first-extension.md) you learned how to create your first extension. In this section you will learn how this extension works under the hood.
|
||||
|
||||
The Hello World sample extension does three things:
|
||||
|
||||
- Implements `onActivate()` and outputs a message to the console.
|
||||
- Implements `onDectivate()` and outputs a message to the console.
|
||||
- Registers `ClusterPage` so that the page is visible in the left-side menu of the cluster dashboard.
|
||||
|
||||
Let's take a closer look at our Hello World sample's source code and see how these three things are achieved.
|
||||
|
||||
## Extension File Structure
|
||||
|
||||
```
|
||||
.
|
||||
├── .gitignore // Ignore build output and node_modules
|
||||
├── Makefile // Config for build tasks that compiles the extension
|
||||
├── README.md // Readable description of your extension's functionality
|
||||
├── src
|
||||
│ └── page.tsx // Extension's additional source code
|
||||
├── main.ts // Source code for extension's main entrypoint
|
||||
├── package.json // Extension manifest and dependencies
|
||||
├── renderer.tsx // Source code for extension's renderer entrypoint
|
||||
├── tsconfig.json // TypeScript configuration
|
||||
├── webpack.config.js // Webpack configuration
|
||||
```
|
||||
|
||||
The extension directory contains the extension's entry files and a few configuration files. Three files: `package.json`, `main.ts` and `renderer.tsx` are essential to understanding the Hello World sample extension. We'll look at those first.
|
||||
|
||||
### Extension Manifest
|
||||
|
||||
Each Lens extension must have a `package.json` file. It contains a mix of Node.js fields, including scripts and dependencies, and Lens-specific fields such as `publisher` and `contributes`. Some of the most-important fields include:
|
||||
|
||||
- `name` and `publisher`: Lens uses `@<publisher>/<name>` as a unique ID for the extension. For example, the Hello World sample has the ID `@lensapp-samples/helloworld-sample`. Lens uses this ID to uniquely identify your extension.
|
||||
- `main`: the extension's entry point run in `main` process.
|
||||
- `renderer`: the extension's entry point run in `renderer` process.
|
||||
- `engines.lens`: the minimum version of Lens API that the extension depends upon.
|
||||
|
||||
``` javascript
|
||||
{
|
||||
"name": "helloworld-sample",
|
||||
"publisher": "lens-samples",
|
||||
"version": "0.0.1",
|
||||
"description": "Lens helloworld-sample",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/lensapp/lens-extension-samples",
|
||||
"engines": {
|
||||
"lens": "^4.0.0"
|
||||
},
|
||||
"main": "dist/main.js",
|
||||
"renderer": "dist/renderer.js",
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"dev": "npm run build --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-open-doodles": "^1.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@k8slens/extensions": "^4.0.0-alpha.2",
|
||||
"ts-loader": "^8.0.4",
|
||||
"typescript": "^4.0.3",
|
||||
"@types/react": "^16.9.35",
|
||||
"@types/node": "^12.0.0",
|
||||
"webpack": "^4.44.2",
|
||||
"webpack-cli": "^3.3.11"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Extension Entry Files
|
||||
|
||||
Lens extensions can have two separate entry files. One file is used in the `main` process of the Lens application and the other is used in the `renderer` process. The `main` entry file exports the class that extends `LensMainExtension`, and the `renderer` entry file exports the class that extends `LensRendererExtension`.
|
||||
|
||||
Both extension classes have `onActivate` and `onDeactivate` methods. The `onActivate` method is executed when your extension is activated. If you need to initialize something in your extension, this is where such an operation should occur. The `onDeactivate` method gives you a chance to clean up before your extension becomes deactivated. For extensions where explicit cleanup is not required, you don't need to override this method. However, if an extension needs to perform an operation when Lens is shutting down (or if the extension is disabled or uninstalled), this is the method where such an operation should occur.
|
||||
|
||||
The Hello World sample extension does not do anything on the `main` process, so we'll focus on the `renderer` process, instead. On the `renderer` entry point, the Hello World sample extension defines the `Cluster Page` object. The `Cluster Page` object registers the `/extension-example` path, and this path renders the `ExamplePage` React component. It also registers the `MenuItem` component that displays the `ExampleIcon` React component and the "Hello World" text in the left-side menu of the cluster dashboard. These React components are defined in the additional `./src/page.tsx` file.
|
||||
|
||||
``` typescript
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { ExampleIcon, ExamplePage } from "./page"
|
||||
import React from "react"
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
clusterPages = [
|
||||
{
|
||||
routePath: "/extension-example",
|
||||
components: {
|
||||
Page: () => <ExamplePage extension={this}/>,
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The Hello World sample extension uses the `Cluster Page` capability, which is just one of the Lens extension API's capabilities. The [Common Capabilities](../capabilities/common-capabilities.md) page will help you home in on the right capabilities to use with your own extensions.
|
||||
19
docs/extensions/get-started/overview.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Extension Development Overview
|
||||
|
||||
This is a general overview to how the development of an extension will procede. For building extensions there will be a few things that you should have installed, and some other things that might be of help.
|
||||
|
||||
### Required:
|
||||
- [Node.js](https://www.nodejs.org/en/)
|
||||
- [Git](https://www.git-scm.com/)
|
||||
- Some sort of text editor – we recommend [VSCode](https://code.visualstudio.com/)
|
||||
- We use [Webpack](https://www.webpack.js.org/) for compilation. All extension need to be at least compatable with a webpack system.
|
||||
|
||||
### Recommended:
|
||||
|
||||
All Lens extensions are javascript packages. We recommend that you program in [Typescript](https://www.typescriptlang.org/) because it catches many common errors.
|
||||
|
||||
Lens is a standard [Electron](https://www.electronjs.org/) application with both main and renderer processes. An extension is made up of two parts, one for each of Lens's core processes. When an extension is loaded, each part is first loaded and issues a notification that it has been loaded. From there, the extension can start doing is work.
|
||||
|
||||
Lens uses [React](https://www.reactjs.org/) as its UI framework and provides some of Lens's own components for reuse with extensions. An extension is resonsible for the lifetime of any resources it spins up. If an extension's main part starts new processes they all must be stopped and cleaned up when the extension is deactivated or unloaded.
|
||||
|
||||
See [Your First Extension](your-first-extension.md) to get started.
|
||||
18
docs/extensions/get-started/wrapping-up.md
Normal file
@ -0,0 +1,18 @@
|
||||
# Wrapping Up
|
||||
|
||||
In [Your First Extension](your-first-extension.md), you learned how to create and run an extension. In [Extension Anatomy](anatomy.md), you learned in detail how a basic extension works. This is just a glimpse into what can be created with Lens extensions. Below are some suggested routes for learning more.
|
||||
|
||||
## Extension Capabilities
|
||||
|
||||
In this section, you'll find information on common extension capabilities, styling information, and a color reference guide. Determine whether your idea for an extension is doable and get ideas for new extensions by reading through the [Common Capabilities](../capabilities/common-capabilities.md) page.
|
||||
|
||||
## Guides and Samples
|
||||
|
||||
Here you'll find a collection of sample extensions that you can use as a base to work from. Some of these samples include a detailed guide that explains the source code. You can find all samples and guides in the [lens-extension-samples](https://github.com/lensapp/lens-extension-samples) repository.
|
||||
|
||||
## Testing and Publishing
|
||||
|
||||
In this section, you can learn:
|
||||
|
||||
* How to add [integration tests](../testing-and-publishing/testing.md) to your extension
|
||||
* How to [publish your extension](../testing-and-publishing/publishing.md)
|
||||
87
docs/extensions/get-started/your-first-extension.md
Normal file
@ -0,0 +1,87 @@
|
||||
# Your First Extension
|
||||
|
||||
In this topic, you'll learn the basics of building extensions by creating an extension that adds a "Hello World" page to a cluster menu.
|
||||
|
||||
## Install the Extension
|
||||
|
||||
To install the extension, clone the [Lens Extension samples](https://github.com/lensapp/lens-extension-samples) repository to your local machine:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/lensapp/lens-extension-samples.git
|
||||
```
|
||||
|
||||
Next you need to create a symlink. A symlink connects the directory that Lens will monitor for user-installed extensions to the sample extension. In this case the sample extension is `helloworld-sample`.
|
||||
|
||||
### Linux & macOS
|
||||
|
||||
```sh
|
||||
mkdir -p ~/.k8slens/extensions
|
||||
cd ~/.k8slens/extensions
|
||||
ln -s lens-extension-samples/helloworld-sample helloworld-sample
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
Create the directory that Lens will monitor for user-installed extensions:
|
||||
|
||||
```sh
|
||||
mkdir C:\Users\<user>\.k8slens\extensions -force
|
||||
cd C:\Users\<user>\.k8slens\extensions
|
||||
```
|
||||
|
||||
If you have administrator rights, you can create symlink to the sample extension – in this case `helloworld-sample`:
|
||||
|
||||
```sh
|
||||
cmd /c mklink /D helloworld-sample lens-extension-samples\helloworld-sample
|
||||
```
|
||||
|
||||
Without administrator rights, you need to copy the extensions sample directory into `C:\Users\<user>\.k8slens\extensions`:
|
||||
|
||||
```
|
||||
Copy-Item 'lens-extension-samples\helloworld-sample' 'C:\Users\<user>\.k8slens\extensions\helloworld-sample'
|
||||
```
|
||||
|
||||
## Build the Extension
|
||||
|
||||
To build the extension you can use `make` or run the `npm` commands manually:
|
||||
|
||||
```sh
|
||||
cd <lens-extension-samples directory>/helloworld-sample
|
||||
make build
|
||||
```
|
||||
|
||||
To run the `npm` commands, enter:
|
||||
|
||||
```sh
|
||||
cd <lens-extension-samples directory>/helloworld-sample
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
Optionally, automatically rebuild the extension by watching for changes to the source code. To do so, enter:
|
||||
|
||||
```sh
|
||||
cd <lens-extension-samples directory>/helloworld-sample
|
||||
npm run dev
|
||||
```
|
||||
|
||||
You must restart Lens for the extension to load. After this initial restart, reload Lens and it will automatically pick up changes any time the extension rebuilds.
|
||||
|
||||
With Lens running, either connect to an existing cluster or [create a new one](../../clusters/adding-clusters.md). You will see the "Hello World" page in the left-side cluster menu.
|
||||
|
||||
## Develop the Extension
|
||||
|
||||
Finally, you'll make a change to the message that our Hello World sample extension displays:
|
||||
|
||||
1. Navigate to `<lens-extension-samples directory>/helloworld-sample`.
|
||||
2. In `page.tsx`, change the message from `HelloWorld!` to `Hello Lens Extensions`.
|
||||
3. Rebuild the extension. If you used `npm run dev`, the extension will rebuild automatically.
|
||||
4. Reload the Lens window.
|
||||
5. Click on the Hello World page.
|
||||
6. The updated message will appear.
|
||||
|
||||
## Next Steps
|
||||
|
||||
In the [next topic](anatomy.md), we'll take a closer look at the source code of our Hello World sample.
|
||||
|
||||
You can find the source code for this tutorial at: [lensapp/lens-extension-samples](https://github.com/lensapp/lens-extension-samples/tree/master/helloworld-sample). [Extension Guides](../guides/README.md) contains additional samples.
|
||||
28
docs/extensions/guides/README.md
Normal file
@ -0,0 +1,28 @@
|
||||
# Extension Guides
|
||||
|
||||
The basics of the Lens Extension API are covered in [Your First Extension](../get-started/your-first-extension.md). In this section detailed code guides and samples are used to explain how to use specific Lens Extension APIs.
|
||||
|
||||
Each guide or sample will include:
|
||||
|
||||
- Clearly commented source code.
|
||||
- Instructions for running the sample extension.
|
||||
- Image of the sample extension's appearance and usage.
|
||||
- Listing of Extension API being used.
|
||||
- Explanation of Extension API concepts.
|
||||
|
||||
## Guides
|
||||
|
||||
| Guide | APIs |
|
||||
| ----- | ----- |
|
||||
| [Main process extension](main-extension.md) | LensMainExtension |
|
||||
| [Renderer process extension](renderer-extension.md) | LensRendererExtension |
|
||||
| [Stores](stores.md) | |
|
||||
| [Components](components.md) | |
|
||||
| [KubeObjectListLayout](kube-object-list-layout.md) | |
|
||||
|
||||
## Samples
|
||||
|
||||
| Sample | APIs |
|
||||
| ----- | ----- |
|
||||
[helloworld](https://github.com/lensapp/lens-extension-samples/tree/master/helloworld-sample) | LensMainExtension <br> LensRendererExtension <br> Component.Icon <br> Component.IconProps |
|
||||
[minikube](https://github.com/lensapp/lens-extension-samples/tree/master/minikube-sample) | LensMainExtension <br> Store.clusterStore <br> Store.workspaceStore |
|
||||
76
docs/extensions/guides/main-extension.md
Normal file
@ -0,0 +1,76 @@
|
||||
# Main Extension
|
||||
|
||||
The main extension api is the interface to Lens' main process (Lens runs in main and renderer processes). It allows you to access, configure, and customize Lens data, add custom application menu items, and generally run custom code in Lens' main process.
|
||||
|
||||
## `LensMainExtension` Class
|
||||
|
||||
To create a main extension simply extend the `LensMainExtension` class:
|
||||
|
||||
``` typescript
|
||||
import { LensMainExtension } from "@k8slens/extensions";
|
||||
|
||||
export default class ExampleExtensionMain extends LensMainExtension {
|
||||
onActivate() {
|
||||
console.log('custom main process extension code started');
|
||||
}
|
||||
|
||||
onDeactivate() {
|
||||
console.log('custom main process extension de-activated');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
There are two methods that you can implement to facilitate running your custom code. `onActivate()` is called when your extension has been successfully enabled. By overriding `onActivate()` you can initiate your custom code. `onDeactivate()` is called when the extension is disabled (typically from the [Lens Extensions Page]()) and when implemented gives you a chance to clean up after your extension, if necessary. The example above simply logs messages when the extension is enabled and disabled. Note that to see standard output from the main process there must be a console connected to it. This is typically achieved by starting Lens from the command prompt.
|
||||
|
||||
The following example is a little more interesting in that it accesses some Lens state data and periodically logs the name of the currently active cluster in Lens.
|
||||
|
||||
``` typescript
|
||||
import { LensMainExtension, Store } from "@k8slens/extensions";
|
||||
|
||||
const clusterStore = Store.clusterStore
|
||||
|
||||
export default class ActiveClusterExtensionMain extends LensMainExtension {
|
||||
|
||||
timer: NodeJS.Timeout
|
||||
|
||||
onActivate() {
|
||||
console.log("Cluster logger activated");
|
||||
this.timer = setInterval(() => {
|
||||
if (!clusterStore.active) {
|
||||
console.log("No active cluster");
|
||||
return;
|
||||
}
|
||||
console.log("active cluster is", clusterStore.active.contextName)
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
onDeactivate() {
|
||||
clearInterval(this.timer)
|
||||
console.log("Cluster logger deactivated");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
See the [Stores](../stores) guide for more details on accessing Lens state data.
|
||||
|
||||
### `appMenus`
|
||||
|
||||
The only UI feature customizable in the main extension api is the application menu. Custom menu items can be inserted and linked to custom functionality, such as navigating to a specific page. The following example demonstrates adding a menu item to the Help menu.
|
||||
|
||||
``` typescript
|
||||
import { LensMainExtension } from "@k8slens/extensions";
|
||||
|
||||
export default class SamplePageMainExtension extends LensMainExtension {
|
||||
appMenus = [
|
||||
{
|
||||
parentId: "help",
|
||||
label: "Sample",
|
||||
click() {
|
||||
console.log("Sample clicked");
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`appMenus` is an array of objects satisfying the `MenuRegistration` interface. `MenuRegistration` extends React's `MenuItemConstructorOptions` interface. `parentId` is the id of the menu to put this menu item under (todo: is this case sensitive and how do we know what the available ids are?), `label` is the text to show on the menu item, and `click()` is called when the menu item is selected. In this example we simply log a message, but typically you would navigate to a specific page or perform some operation. Pages are associated with the [`LensRendererExtension`](renderer-extension.md) class and can be defined when you extend it.
|
||||
1
docs/extensions/guides/renderer-extension.md
Normal file
@ -0,0 +1 @@
|
||||
# Renderer Extension
|
||||
0
docs/extensions/testing-and-publishing/bundling.md
Normal file
38
docs/extensions/testing-and-publishing/testing.md
Normal file
@ -0,0 +1,38 @@
|
||||
# Testing Extensions
|
||||
|
||||
## Console.log
|
||||
|
||||
Extension developers might find `console.log()` useful for printing out information and errors from extensions. To use `console.log()`, note that Lens is based on Electron, and that Electron has two types of processes: [Main and Renderer](https://www.electronjs.org/docs/tutorial/quick-start#main-and-renderer-processes).
|
||||
|
||||
### Renderer Process Logs
|
||||
|
||||
In the Renderer process, `console.log()` is printed in the Console in Developer Tools (**View** > **Toggle Developer Tools**).
|
||||
|
||||
### Main Process Logs
|
||||
|
||||
Viewing the logs from the Main process is a little trickier, since they cannot be printed using Developer Tools.
|
||||
|
||||
#### macOS
|
||||
|
||||
On macOS, view the Main process logs by running Lens from the terminal:
|
||||
|
||||
```bash
|
||||
/Applications/Lens.app/Contents/MacOS/Lens
|
||||
```
|
||||
|
||||
You can also use [Console.app](https://support.apple.com/en-gb/guide/console/welcome/mac) to view the Main process logs.
|
||||
|
||||
#### Linux
|
||||
|
||||
On Linux, you can access the Main process logs using the Lens PID. First get the PID:
|
||||
|
||||
```bash
|
||||
ps aux | grep Lens | grep -v grep
|
||||
```
|
||||
|
||||
Then get the Main process logs using the PID:
|
||||
|
||||
```bash
|
||||
tail -f /proc/[pid]/fd/1 # stdout (console.log)
|
||||
tail -f /proc/[pid]/fd/2 # stdout (console.error)
|
||||
```
|
||||
18
docs/extensions/typedoc-readme.md.tpl
Normal file
@ -0,0 +1,18 @@
|
||||
# Extension API Reference
|
||||
|
||||
## Modules
|
||||
|
||||
* [App](modules/_core_api_app_.md)
|
||||
* [ClusterFeature](modules/_core_api_cluster_feature_.md)
|
||||
* [EventBus](modules/_core_api_event_bus_.md)
|
||||
* [Store](modules/_core_api_stores_.md)
|
||||
* [Util](modules/_core_api_utils_.md)
|
||||
* [Component](modules/_renderer_api_components_.md)
|
||||
* [K8sApi](modules/_renderer_api_k8s_api_.md)
|
||||
* [Navigation](modules/_renderer_api_navigation_.md)
|
||||
|
||||
## Classes
|
||||
|
||||
* [LensMainExtension](classes/lensmainextension.md)
|
||||
* [LensRendererExtension](classes/lensrendererextension.md)
|
||||
|
||||
3
docs/extensions/usage/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Using Extensions
|
||||
|
||||
TBD
|
||||
1
docs/faq/README.md
Normal file
@ -0,0 +1 @@
|
||||
TBD
|
||||
55
docs/getting-started/README.md
Normal file
@ -0,0 +1,55 @@
|
||||
# Getting Started
|
||||
|
||||
Lens is lightweight and simple to install. You'll be up and running in just a few minutes.
|
||||
|
||||
|
||||
## System Requirements
|
||||
|
||||
Review the [System Requirements](/supporting/requirements/) to check if your computer configuration is supported.
|
||||
|
||||
|
||||
## macOS
|
||||
|
||||
1. [Download Lens](https://github.com/lensapp/lens/releases) for macOS.
|
||||
2. Open the browser's download list and locate the downloaded archive.
|
||||
3. Select the 'magnifying glass' icon to open the archive in Finder.
|
||||
4. Double-click `Lens-{version}.dmg` and drag `Lens.app` to the `Applications` folder, making it available in the macOS Launchpad.
|
||||
5. Add Lens to your Dock by right-clicking on the icon to bring up the context menu and choosing **Options**, **Keep in Dock**.
|
||||
|
||||
|
||||
## Windows
|
||||
|
||||
1. Download the [Lens installer](https://github.com/lensapp/lens/releases) for Windows.
|
||||
2. Once it is downloaded, run the installer `Lens-Setup-{version}.exe`. This will only take a minute.
|
||||
3. By default, Lens is installed under `C:\users\{username}\AppData\Local\Programs\Lens`.
|
||||
|
||||
|
||||
## Linux
|
||||
|
||||
See the [Download Lens](https://github.com/lensapp/lens/releases) page for a complete list of available installation options.
|
||||
|
||||
|
||||
### Snap
|
||||
|
||||
Lens is officially distributed as a Snap package in the [Snap Store](https://snapcraft.io/store):
|
||||
|
||||
[](https://snapcraft.io/kontena-lens)
|
||||
|
||||
You can install it by running:
|
||||
|
||||
```bash
|
||||
sudo snap install kontena-lens --classic
|
||||
```
|
||||
|
||||
## Update Cadence
|
||||
|
||||
Lens releases a new version each month with new features and important bug fixes. Lens supports auto updating and you will be prompted to install the new release when it becomes available!
|
||||
|
||||
To stay current with the Lens features, you can review the [release notes](https://github.com/lensapp/lens/releases).
|
||||
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Add clusters](../clusters/adding-clusters.md)
|
||||
- [Watch introductory videos](./introductory-videos.md)
|
||||
|
||||
BIN
docs/getting-started/images/color-theme.png
Normal file
|
After Width: | Height: | Size: 131 KiB |
|
After Width: | Height: | Size: 124 KiB |
BIN
docs/getting-started/images/snap-store.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
36
docs/getting-started/introductory-videos.md
Normal file
@ -0,0 +1,36 @@
|
||||
# Introductory Videos
|
||||
|
||||
Continue your Lens journey with this set of introductory videos! These videos are meant to quickly familiarize you with Lens' various powerful features.
|
||||
|
||||
<ul class="video-list">
|
||||
<li class="video">
|
||||
<a target="_blank" href="https://youtu.be/mc-BzPDKfkQ">
|
||||
<img src="https://img.youtube.com/vi/mc-BzPDKfkQ/mqdefault.jpg" alt aria-hidden="true" class="thumb"/>
|
||||
<div class="info">
|
||||
<h3 class="title">Getting started</h3>
|
||||
<p class="description">Get Lens Kubernetes IDE Running in 5 Minutes</p>
|
||||
<span class="duration"><span class="sr-only">Duration </span>35<span class="sr-only"> minutes</span></span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="video">
|
||||
<a target="_blank" href="https://youtu.be/epw_MjxjMYI">
|
||||
<img src="https://img.youtube.com/vi/epw_MjxjMYI/mqdefault.jpg" alt aria-hidden="true" class="thumb"/>
|
||||
<div class="info">
|
||||
<h3 class="title">Introducing Lens</h3>
|
||||
<p class="description">Lens Kubernetes IDE overview</p>
|
||||
<span class="duration"><span class="sr-only">Duration </span>2<span class="sr-only"> minutes</span></span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="video">
|
||||
<a target="_blank" href="https://youtu.be/fqneoWCgJdw">
|
||||
<img src="https://img.youtube.com/vi/fqneoWCgJdw/mqdefault.jpg" alt aria-hidden="true" class="thumb"/>
|
||||
<div class="info">
|
||||
<h3 class="title">Demo of Mirantis Lens</h3>
|
||||
<p class="description">The Best IDE For Kubernetes</p>
|
||||
<span class="duration"><span class="sr-only">Duration </span>10<span class="sr-only"> minutes</span></span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
28
docs/getting-started/preferences.md
Normal file
@ -0,0 +1,28 @@
|
||||
# Preferences
|
||||
|
||||
|
||||
## Color Themes
|
||||
|
||||
The Color Themes option in Lens preferences lets you set the colors in the Lens user interface to suit your liking.
|
||||
|
||||
1. Go to **File** > **Preferences** (**Lens** > **Preferences** on Mac).
|
||||
2. Select your preferred theme from the **Color Theme** dropdown.
|
||||

|
||||
|
||||
|
||||
## Telemetry & Usage Tracking
|
||||
|
||||
Lens collects telemetry data, which is used to help us understand how to improve the product. For example, this usage data helps us to debug issues and to prioritize new features. While we appreciate the insights this data provides, we also know that not everyone wants to send usage data. Please see our [privacy statement](https://www.mirantis.com/company/privacy-policy/) to learn more.
|
||||
|
||||
|
||||
### Disable Telemetry Reporting
|
||||
|
||||
If you don't wish to send usage data to Mirantis, you can disable the "Telemetry & Usage Tracking" in the Lens preferences.
|
||||
|
||||
1. Go to **File** > **Preferences** (**Lens** > **Preferences** on Mac).
|
||||
2. Scroll down to **Telemetry & Usage Tracking**
|
||||
3. Uncheck **Allow Telemetry & Usage Tracking**.
|
||||
|
||||
This will silence all telemetry events from Lens going forward. Telemetry information may have been collected and sent up until the point when you disable this setting.
|
||||

|
||||
|
||||
3
docs/helm/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Using Helm Charts
|
||||
|
||||
TBD
|
||||
BIN
docs/img/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
docs/img/lens-intro-video-screenshot.png
Normal file
|
After Width: | Height: | Size: 754 KiB |
21
docs/img/lens-logo-icon.svg
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;}
|
||||
.st1{fill:#3D90CE;}
|
||||
.st2{fill:#FFFFFF;}
|
||||
</style>
|
||||
<rect y="0" class="st0" width="512" height="512"/>
|
||||
<rect x="16" y="16" class="st1" width="480" height="480"/>
|
||||
<g>
|
||||
<path class="st2" d="M242.6,426h130.9l-30.2-128.7L242.6,426z"/>
|
||||
<path class="st2" d="M86,352.5V426h137.6l57.5-73.5H86z"/>
|
||||
<path class="st2" d="M273.1,167L426,241.4v-148L273.1,167z"/>
|
||||
<path class="st2" d="M388.9,426H426V258l-86.4-42.1L388.9,426z"/>
|
||||
<path class="st2" d="M406.9,86H216.4l-23,102.7L406.9,86z"/>
|
||||
<path class="st2" d="M86,195.1v142.5h113.3L86,195.1z"/>
|
||||
<path class="st2" d="M201.1,86H86v85.1l75,94.3L201.1,86z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 999 B |
1
docs/img/play.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 22 22"><path fill="#fff" d="M9.35 15.95V6.6L15.4 11zM11 1C5.477 1 1 5.477 1 11c0 5.522 4.477 10 10 10s10-4.478 10-10c0-5.523-4.477-10-10-10zm0 18.5a8.5 8.5 0 1 1 .001-17.001A8.5 8.5 0 0 1 11 19.5z"/></svg>
|
||||
|
After Width: | Height: | Size: 283 B |
90
docs/stylesheets/extra.css
Normal file
@ -0,0 +1,90 @@
|
||||
:root {
|
||||
--md-primary-fg-color: #3d90ce;
|
||||
--md-accent-fg-color: #3d90ce;
|
||||
}
|
||||
|
||||
:root > * {
|
||||
/* Footer */
|
||||
--md-footer-bg-color: #3d90ce;
|
||||
}
|
||||
|
||||
.md-version__list {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
ul.video-list {
|
||||
counter-reset: section;
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
position:relative
|
||||
}
|
||||
|
||||
ul.video-list .video:not(:last-of-type) a {
|
||||
border-bottom:2px solid #e6e6e6
|
||||
}
|
||||
|
||||
ul.video-list a {
|
||||
position: relative;
|
||||
padding: 2rem 2rem 2rem 4.2rem;
|
||||
display: block;
|
||||
box-sizing:border-box
|
||||
}
|
||||
|
||||
ul.video-list a .info {
|
||||
padding-top:0.25rem
|
||||
}
|
||||
|
||||
ul.video-list a .info::before {
|
||||
counter-increment: section;
|
||||
content: counter(section);
|
||||
position: absolute;
|
||||
left: 1.5rem;
|
||||
color:black
|
||||
}
|
||||
|
||||
ul.video-list a .info > p, ul.video-list a .info > span {
|
||||
color:black
|
||||
}
|
||||
|
||||
ul.video-list a .info .title {
|
||||
margin-top: 0;
|
||||
margin-bottom:0.7rem
|
||||
}
|
||||
|
||||
ul.video-list a .info .description {
|
||||
margin-bottom: 1rem;
|
||||
|
||||
}
|
||||
|
||||
ul.video-list a .info .duration, ul.video-list a .info .duration span {
|
||||
color: #6e6e6e;
|
||||
|
||||
}
|
||||
|
||||
ul.video-list a:hover, ul.video-list a:focus {
|
||||
text-decoration:none
|
||||
}
|
||||
|
||||
ul.video-list a:hover {
|
||||
background:#f2f2f2
|
||||
}
|
||||
|
||||
ul.video-list a:hover::after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 6rem;
|
||||
height: 6rem;
|
||||
position: absolute;
|
||||
background: url("/img/play.svg");
|
||||
background-size: 6rem;
|
||||
top: 3rem;
|
||||
left:8.6rem
|
||||
}
|
||||
|
||||
ul.video-list .thumb {
|
||||
max-height: 8.2rem;
|
||||
padding-right: 2rem;
|
||||
position: relative;
|
||||
float:left
|
||||
}
|
||||
|
||||
26
docs/supporting/requirements.md
Normal file
@ -0,0 +1,26 @@
|
||||
# Requirements for Lens
|
||||
|
||||
## Hardware
|
||||
|
||||
Lens is a small download (< 300 MB) and has a disk footprint of 600 MB. Lens is lightweight and should easily run on today's hardware.
|
||||
|
||||
We recommend:
|
||||
|
||||
* 2 GHz or faster processor
|
||||
* 1 GB of RAM
|
||||
|
||||
## Platforms
|
||||
|
||||
Lens has been tested on the following platforms:
|
||||
|
||||
* macOS
|
||||
* Windows
|
||||
* Linux
|
||||
|
||||
### Additional Windows requirements
|
||||
|
||||
...
|
||||
|
||||
### Additional Linux Requirements
|
||||
|
||||
...
|
||||
@ -1,8 +0,0 @@
|
||||
install-deps:
|
||||
yarn install
|
||||
|
||||
build: install-deps
|
||||
yarn run build
|
||||
|
||||
test:
|
||||
yarn run test
|
||||
@ -2,10 +2,10 @@ import { LensMainExtension } from "@k8slens/extensions";
|
||||
|
||||
export default class ExampleExtensionMain extends LensMainExtension {
|
||||
onActivate() {
|
||||
console.log('EXAMPLE EXTENSION MAIN: ACTIVATED', this.getMeta());
|
||||
console.log('EXAMPLE EXTENSION MAIN: ACTIVATED', this.name, this.id);
|
||||
}
|
||||
|
||||
onDeactivate() {
|
||||
console.log('EXAMPLE EXTENSION MAIN: DEACTIVATED', this.getMeta());
|
||||
console.log('EXAMPLE EXTENSION MAIN: DEACTIVATED', this.name, this.id);
|
||||
}
|
||||
}
|
||||
|
||||
3749
extensions/example-extension/package-lock.json
generated
@ -11,13 +11,14 @@
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"dev": "npm run build --watch",
|
||||
"test": "echo NO TESTS"
|
||||
"test": "jest --passWithNoTests --env=jsdom src $@"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-open-doodles": "^1.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@k8slens/extensions": "file:../../src/extensions/npm/extensions",
|
||||
"jest": "^26.6.3",
|
||||
"ts-loader": "^8.0.4",
|
||||
"typescript": "^4.0.3",
|
||||
"webpack": "^4.44.2"
|
||||
|
||||
@ -5,11 +5,21 @@ import React from "react"
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
clusterPages = [
|
||||
{
|
||||
path: "/extension-example",
|
||||
id: "example",
|
||||
routePath: "/extension-example",
|
||||
title: "Example Extension",
|
||||
components: {
|
||||
Page: () => <ExamplePage extension={this}/>,
|
||||
MenuIcon: ExampleIcon,
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
clusterPageMenus = [
|
||||
{
|
||||
target: { pageId: "example", params: {} },
|
||||
title: "Example Extension",
|
||||
components: {
|
||||
Icon: ExampleIcon,
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
8
extensions/kube-object-event-status/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
install-deps:
|
||||
npm install
|
||||
|
||||
build: install-deps
|
||||
npm run build
|
||||
|
||||
test:
|
||||
npm run test
|
||||
3512
extensions/kube-object-event-status/package-lock.json
generated
Normal file
24
extensions/kube-object-event-status/package.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "kube-object-event-status",
|
||||
"version": "0.1.0",
|
||||
"description": "Adds kube object status from events",
|
||||
"renderer": "dist/renderer.js",
|
||||
"lens": {
|
||||
"metadata": {},
|
||||
"styles": []
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"dev": "npm run build --watch",
|
||||
"test": "echo NO TESTS"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@k8slens/extensions": "file:../../src/extensions/npm/extensions",
|
||||
"ts-loader": "^8.0.4",
|
||||
"typescript": "^4.0.3",
|
||||
"webpack": "^4.44.2",
|
||||
"mobx": "^5.15.5",
|
||||
"react": "^16.13.1"
|
||||
}
|
||||
}
|
||||
42
extensions/kube-object-event-status/renderer.tsx
Normal file
@ -0,0 +1,42 @@
|
||||
import { LensRendererExtension, K8sApi } from "@k8slens/extensions";
|
||||
import { resolveStatus, resolveStatusForCronJobs, resolveStatusForPods } from "./src/resolver"
|
||||
|
||||
export default class EventResourceStatusRendererExtension extends LensRendererExtension {
|
||||
kubeObjectStatusTexts = [
|
||||
{
|
||||
kind: "Pod",
|
||||
apiVersions: ["v1"],
|
||||
resolve: (pod: K8sApi.Pod) => resolveStatusForPods(pod)
|
||||
},
|
||||
{
|
||||
kind: "ReplicaSet",
|
||||
apiVersions: ["v1"],
|
||||
resolve: (replicaSet: K8sApi.ReplicaSet) => resolveStatus(replicaSet)
|
||||
},
|
||||
{
|
||||
kind: "Deployment",
|
||||
apiVersions: ["apps/v1"],
|
||||
resolve: (deployment: K8sApi.Deployment) => resolveStatus(deployment)
|
||||
},
|
||||
{
|
||||
kind: "StatefulSet",
|
||||
apiVersions: ["apps/v1"],
|
||||
resolve: (statefulSet: K8sApi.StatefulSet) => resolveStatus(statefulSet)
|
||||
},
|
||||
{
|
||||
kind: "DaemonSet",
|
||||
apiVersions: ["apps/v1"],
|
||||
resolve: (daemonSet: K8sApi.DaemonSet) => resolveStatus(daemonSet)
|
||||
},
|
||||
{
|
||||
kind: "Job",
|
||||
apiVersions: ["batch/v1"],
|
||||
resolve: (job: K8sApi.Job) => resolveStatus(job)
|
||||
},
|
||||
{
|
||||
kind: "CronJob",
|
||||
apiVersions: ["batch/v1"],
|
||||
resolve: (cronJob: K8sApi.CronJob) => resolveStatusForCronJobs(cronJob)
|
||||
},
|
||||
]
|
||||
}
|
||||
52
extensions/kube-object-event-status/src/resolver.tsx
Normal file
@ -0,0 +1,52 @@
|
||||
import { K8sApi } from "@k8slens/extensions";
|
||||
|
||||
export function resolveStatus(object: K8sApi.KubeObject): K8sApi.KubeObjectStatus {
|
||||
const eventStore = K8sApi.apiManager.getStore(K8sApi.eventApi)
|
||||
const events = (eventStore as K8sApi.EventStore).getEventsByObject(object);
|
||||
let warnings = events.filter(evt => evt.isWarning());
|
||||
if (!events.length || !warnings.length) {
|
||||
return null;
|
||||
}
|
||||
const event = [...warnings, ...events][0]; // get latest event
|
||||
return {
|
||||
level: K8sApi.KubeObjectStatusLevel.WARNING,
|
||||
text: `${event.message}`,
|
||||
timestamp: event.metadata.creationTimestamp
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveStatusForPods(pod: K8sApi.Pod): K8sApi.KubeObjectStatus {
|
||||
if (!pod.hasIssues()) {
|
||||
return null
|
||||
}
|
||||
const eventStore = K8sApi.apiManager.getStore(K8sApi.eventApi)
|
||||
const events = (eventStore as K8sApi.EventStore).getEventsByObject(pod);
|
||||
let warnings = events.filter(evt => evt.isWarning());
|
||||
if (!events.length || !warnings.length) {
|
||||
return null;
|
||||
}
|
||||
const event = [...warnings, ...events][0]; // get latest event
|
||||
return {
|
||||
level: K8sApi.KubeObjectStatusLevel.WARNING,
|
||||
text: `${event.message}`,
|
||||
timestamp: event.metadata.creationTimestamp
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveStatusForCronJobs(cronJob: K8sApi.CronJob): K8sApi.KubeObjectStatus {
|
||||
const eventStore = K8sApi.apiManager.getStore(K8sApi.eventApi)
|
||||
let events = (eventStore as K8sApi.EventStore).getEventsByObject(cronJob);
|
||||
let warnings = events.filter(evt => evt.isWarning());
|
||||
if (cronJob.isNeverRun()) {
|
||||
events = events.filter(event => event.reason != "FailedNeedsStart");
|
||||
}
|
||||
if (!events.length || !warnings.length) {
|
||||
return null;
|
||||
}
|
||||
const event = [...warnings, ...events][0]; // get latest event
|
||||
return {
|
||||
level: K8sApi.KubeObjectStatusLevel.WARNING,
|
||||
text: `${event.message}`,
|
||||
timestamp: event.metadata.creationTimestamp
|
||||
}
|
||||
}
|
||||
26
extensions/kube-object-event-status/tsconfig.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"module": "CommonJS",
|
||||
"target": "ES2017",
|
||||
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
||||
"moduleResolution": "Node",
|
||||
"sourceMap": false,
|
||||
"declaration": false,
|
||||
"strict": false,
|
||||
"noImplicitAny": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"experimentalDecorators": true,
|
||||
"jsx": "react"
|
||||
},
|
||||
"include": [
|
||||
"./*.ts",
|
||||
"./*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"*.js"
|
||||
]
|
||||
}
|
||||
35
extensions/kube-object-event-status/webpack.config.js
Normal file
@ -0,0 +1,35 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
entry: './renderer.tsx',
|
||||
context: __dirname,
|
||||
target: "electron-renderer",
|
||||
mode: "production",
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
use: 'ts-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
],
|
||||
},
|
||||
externals: [
|
||||
{
|
||||
"@k8slens/extensions": "var global.LensExtensions",
|
||||
"react": "var global.React",
|
||||
"mobx": "var global.Mobx"
|
||||
}
|
||||
],
|
||||
resolve: {
|
||||
extensions: [ '.tsx', '.ts', '.js' ],
|
||||
},
|
||||
output: {
|
||||
libraryTarget: "commonjs2",
|
||||
globalObject: "this",
|
||||
filename: 'renderer.js',
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
},
|
||||
},
|
||||
];
|
||||
@ -1,8 +0,0 @@
|
||||
install-deps:
|
||||
yarn install
|
||||
|
||||
build: install-deps
|
||||
yarn run build
|
||||
|
||||
test:
|
||||
yarn run test
|
||||
3695
extensions/license-menu-item/package-lock.json
generated
@ -6,12 +6,13 @@
|
||||
"scripts": {
|
||||
"build": "webpack -p",
|
||||
"dev": "webpack --watch",
|
||||
"test": "echo NO TESTS"
|
||||
"test": "jest --passWithNoTests --env=jsdom src $@"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@types/webpack": "^4.41.17",
|
||||
"@k8slens/extensions": "file:../../src/extensions/npm/extensions",
|
||||
"@types/webpack": "^4.41.17",
|
||||
"jest": "^26.6.3",
|
||||
"mobx": "^5.15.5",
|
||||
"react": "^16.13.1",
|
||||
"ts-loader": "^8.0.4",
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
install-deps:
|
||||
yarn install
|
||||
|
||||
build: install-deps
|
||||
yarn run build
|
||||
|
||||
test:
|
||||
yarn run test
|
||||
3811
extensions/metrics-cluster-feature/package-lock.json
generated
@ -10,17 +10,18 @@
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"dev": "npm run build --watch",
|
||||
"test": "echo NO TESTS"
|
||||
"test": "jest --passWithNoTests --env=jsdom src $@"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": "^7.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@k8slens/extensions": "file:../../src/extensions/npm/extensions",
|
||||
"jest": "^26.6.3",
|
||||
"mobx": "^5.15.5",
|
||||
"react": "^16.13.1",
|
||||
"ts-loader": "^8.0.4",
|
||||
"typescript": "^4.0.3",
|
||||
"webpack": "^4.44.2",
|
||||
"mobx": "^5.15.5",
|
||||
"react": "^16.13.1"
|
||||
"webpack": "^4.44.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
install-deps:
|
||||
yarn install
|
||||
|
||||
build: install-deps
|
||||
yarn run build
|
||||
|
||||
test:
|
||||
yarn run test
|
||||
3719
extensions/node-menu/package-lock.json
generated
@ -10,15 +10,16 @@
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"dev": "npm run build --watch",
|
||||
"test": "echo NO TESTS"
|
||||
"test": "jest --passWithNoTests --env=jsdom src $@"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@k8slens/extensions": "file:../../src/extensions/npm/extensions",
|
||||
"jest": "^26.6.3",
|
||||
"mobx": "^5.15.5",
|
||||
"react": "^16.13.1",
|
||||
"ts-loader": "^8.0.4",
|
||||
"typescript": "^4.0.3",
|
||||
"webpack": "^4.44.2",
|
||||
"mobx": "^5.15.5",
|
||||
"react": "^16.13.1"
|
||||
"webpack": "^4.44.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
install-deps:
|
||||
yarn install
|
||||
|
||||
build: install-deps
|
||||
yarn run build
|
||||
|
||||
test:
|
||||
yarn run test
|
||||
3719
extensions/pod-menu/package-lock.json
generated
@ -10,15 +10,16 @@
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"dev": "npm run build --watch",
|
||||
"test": "echo NO TESTS"
|
||||
"test": "jest --passWithNoTests --env=jsdom src $@"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"ts-loader": "^8.0.4",
|
||||
"typescript": "^4.0.3",
|
||||
"webpack": "^4.44.2",
|
||||
"@k8slens/extensions": "file:../../src/extensions/npm/extensions",
|
||||
"jest": "^26.6.3",
|
||||
"mobx": "^5.15.5",
|
||||
"react": "^16.13.1",
|
||||
"@k8slens/extensions": "file:../../src/extensions/npm/extensions"
|
||||
"ts-loader": "^8.0.4",
|
||||
"typescript": "^4.0.3",
|
||||
"webpack": "^4.44.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
install-deps:
|
||||
yarn install
|
||||
|
||||
build: install-deps
|
||||
yarn run build
|
||||
|
||||
test:
|
||||
yarn run test
|
||||
@ -1,13 +1,12 @@
|
||||
import { LensMainExtension, windowManager } from "@k8slens/extensions";
|
||||
import { supportPageURL } from "./src/support.route";
|
||||
import { LensMainExtension } from "@k8slens/extensions";
|
||||
|
||||
export default class SupportPageMainExtension extends LensMainExtension {
|
||||
appMenus = [
|
||||
{
|
||||
parentId: "help",
|
||||
label: "Support",
|
||||
click() {
|
||||
windowManager.navigate(supportPageURL());
|
||||
click: () => {
|
||||
this.navigate();
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
4613
extensions/support-page/package-lock.json
generated
@ -7,7 +7,7 @@
|
||||
"scripts": {
|
||||
"build": "webpack -p",
|
||||
"dev": "webpack --watch",
|
||||
"test": "echo NO TESTS"
|
||||
"test": "jest --passWithNoTests --env=jsdom src $@"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
@ -16,6 +16,7 @@
|
||||
"@types/react-router": "^5.1.8",
|
||||
"@types/webpack": "^4.41.17",
|
||||
"css-loader": "^5.0.0",
|
||||
"jest": "^26.6.3",
|
||||
"mobx": "^5.15.5",
|
||||
"react": "^16.13.1",
|
||||
"sass-loader": "^10.0.4",
|
||||
|
||||
@ -1,28 +1,21 @@
|
||||
import React from "react";
|
||||
import { Component, LensRendererExtension, Navigation } from "@k8slens/extensions";
|
||||
import { supportPageRoute, supportPageURL } from "./src/support.route";
|
||||
import { Support } from "./src/support";
|
||||
import { Component, Interface, LensRendererExtension } from "@k8slens/extensions";
|
||||
import { SupportPage } from "./src/support";
|
||||
|
||||
export default class SupportPageRendererExtension extends LensRendererExtension {
|
||||
globalPages = [
|
||||
globalPages: Interface.PageRegistration[] = [
|
||||
{
|
||||
...supportPageRoute,
|
||||
url: supportPageURL(),
|
||||
hideInMenu: true,
|
||||
components: {
|
||||
Page: Support,
|
||||
Page: SupportPage,
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
statusBarItems = [
|
||||
statusBarItems: Interface.StatusBarRegistration[] = [
|
||||
{
|
||||
item: (
|
||||
<div
|
||||
className="flex align-center gaps hover-highlight"
|
||||
onClick={() => Navigation.navigate(supportPageURL())}
|
||||
>
|
||||
<Component.Icon material="help" smallest />
|
||||
<div className="SupportPageIcon flex align-center" onClick={() => this.navigate()}>
|
||||
<Component.Icon interactive material="help" smallest/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
import type { RouteProps } from "react-router";
|
||||
|
||||
export const supportPageRoute: RouteProps = {
|
||||
path: "/support"
|
||||
}
|
||||
|
||||
export const supportPageURL = () => supportPageRoute.path.toString();
|
||||
@ -1,4 +1,4 @@
|
||||
.PageLayout.Support {
|
||||
.SupportPage {
|
||||
a[target=_blank] {
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid;
|
||||
@ -10,4 +10,10 @@
|
||||
margin-left: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.SupportPageIcon {
|
||||
color: white;
|
||||
font-size: var(--font-size-small);
|
||||
padding-right: calc(var(--padding) / 2);
|
||||
}
|
||||
@ -6,12 +6,12 @@ import { observer } from "mobx-react"
|
||||
import { App, Component } from "@k8slens/extensions";
|
||||
|
||||
@observer
|
||||
export class Support extends React.Component {
|
||||
export class SupportPage extends React.Component {
|
||||
render() {
|
||||
const { PageLayout } = Component;
|
||||
const { slackUrl, issuesTrackerUrl } = App;
|
||||
return (
|
||||
<PageLayout showOnTop className="Support" header={<h2>Support</h2>}>
|
||||
<PageLayout showOnTop className="SupportPage" header={<h2>Support</h2>}>
|
||||
<h2>Community Slack Channel</h2>
|
||||
<p>
|
||||
Ask a question, see what's being discussed, join the conversation <a href={slackUrl} target="_blank">here</a>
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
install-deps:
|
||||
yarn install
|
||||
|
||||
build: install-deps
|
||||
yarn run build
|
||||
|
||||
test:
|
||||
yarn run test
|
||||
3504
extensions/telemetry/package-lock.json
generated
@ -11,19 +11,20 @@
|
||||
"scripts": {
|
||||
"build": "webpack -p",
|
||||
"dev": "webpack --watch",
|
||||
"test": "echo NO TESTS"
|
||||
"test": "jest --passWithNoTests --env=jsdom src $@"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@k8slens/extensions": "file:../../src/extensions/npm/extensions",
|
||||
"@types/analytics-node": "^3.1.3",
|
||||
"analytics-node": "^3.4.0-beta.3",
|
||||
"jest": "^26.6.3",
|
||||
"mobx": "^5.15.5",
|
||||
"node-machine-id": "^1.1.12",
|
||||
"react": "^16.13.1",
|
||||
"ts-loader": "^8.0.4",
|
||||
"typescript": "^4.0.3",
|
||||
"webpack": "^4.44.2",
|
||||
"mobx": "^5.15.5",
|
||||
"react": "^16.13.1",
|
||||
"node-machine-id": "^1.1.12",
|
||||
"universal-analytics": "^0.4.23",
|
||||
"analytics-node": "^3.4.0-beta.3"
|
||||
"webpack": "^4.44.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ const itif = (condition: boolean) => condition ? it : it.skip
|
||||
|
||||
jest.setTimeout(60000)
|
||||
|
||||
// FIXME (!): improve / simplify all css-selectors + use [data-test-id="some-id"] (already used in some tests below)
|
||||
describe("Lens integration tests", () => {
|
||||
const TEST_NAMESPACE = "integration-tests"
|
||||
|
||||
@ -47,17 +48,23 @@ describe("Lens integration tests", () => {
|
||||
await clickWhatsNew(app)
|
||||
})
|
||||
|
||||
// Todo figure out how to access main menu to get these to work
|
||||
it.skip('shows "add cluster"', async () => {
|
||||
await app.client.keys(['Shift', 'Meta', 'A'])
|
||||
it('shows "add cluster"', async () => {
|
||||
await app.electron.ipcRenderer.send('test-menu-item-click', "File", "Add Cluster")
|
||||
await app.client.waitUntilTextExists("h2", "Add Cluster")
|
||||
await app.client.keys(['Shift', 'Meta'])
|
||||
})
|
||||
|
||||
it.skip('shows "preferences"', async () => {
|
||||
await app.client.keys(['Meta', ','])
|
||||
await app.client.waitUntilTextExists("h2", "Preferences")
|
||||
await app.client.keys('Meta')
|
||||
describe("preferences page", () => {
|
||||
it('shows "preferences"', async () => {
|
||||
let appName: string = process.platform === "darwin" ? "Lens" : "File"
|
||||
await app.electron.ipcRenderer.send('test-menu-item-click', appName, "Preferences")
|
||||
await app.client.waitUntilTextExists("h2", "Preferences")
|
||||
})
|
||||
|
||||
it('ensures helm repos', async () => {
|
||||
await app.client.waitUntilTextExists("div.repos #message-stable", "stable") // wait for the helm-cli to fetch the stable repo
|
||||
await app.client.click("#HelmRepoSelect") // click the repo select to activate the drop-down
|
||||
await app.client.waitUntilTextExists("div.Select__option", "") // wait for at least one option to appear (any text)
|
||||
})
|
||||
})
|
||||
|
||||
it.skip('quits Lens"', async () => {
|
||||
@ -388,7 +395,7 @@ describe("Lens integration tests", () => {
|
||||
if (drawer !== "") {
|
||||
it(`shows ${drawer} drawer`, async () => {
|
||||
expect(clusterAdded).toBe(true)
|
||||
await app.client.click(`.sidebar-nav #${drawerId} span.link-text`)
|
||||
await app.client.click(`.sidebar-nav [data-test-id="${drawerId}"] span.link-text`)
|
||||
await app.client.waitUntilTextExists(`a[href^="/${pages[0].href}"]`, pages[0].name)
|
||||
})
|
||||
}
|
||||
@ -403,13 +410,47 @@ describe("Lens integration tests", () => {
|
||||
// hide the drawer
|
||||
it(`hides ${drawer} drawer`, async () => {
|
||||
expect(clusterAdded).toBe(true)
|
||||
await app.client.click(`.sidebar-nav #${drawerId} span.link-text`)
|
||||
await app.client.click(`.sidebar-nav [data-test-id="${drawerId}"] span.link-text`)
|
||||
await expect(app.client.waitUntilTextExists(`a[href^="/${pages[0].href}"]`, pages[0].name, 100)).rejects.toThrow()
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe("viewing pod logs", () => {
|
||||
beforeEach(appStartAddCluster, 40000)
|
||||
|
||||
afterEach(async () => {
|
||||
if (app && app.isRunning()) {
|
||||
return util.tearDown(app)
|
||||
}
|
||||
})
|
||||
|
||||
it(`shows a logs for a pod`, async () => {
|
||||
expect(clusterAdded).toBe(true)
|
||||
// Go to Pods page
|
||||
await app.client.click(".sidebar-nav [data-test-id='workloads'] span.link-text")
|
||||
await app.client.waitUntilTextExists('a[href^="/pods"]', "Pods")
|
||||
await app.client.click('a[href^="/pods"]')
|
||||
await app.client.waitUntilTextExists("div.TableCell", "kube-apiserver")
|
||||
// Open logs tab in dock
|
||||
await app.client.click(".list .TableRow:first-child")
|
||||
await app.client.waitForVisible(".Drawer")
|
||||
await app.client.click(".drawer-title .Menu li:nth-child(2)")
|
||||
// Check if controls are available
|
||||
await app.client.waitForVisible(".PodLogs .VirtualList")
|
||||
await app.client.waitForVisible(".PodLogControls")
|
||||
await app.client.waitForVisible(".PodLogControls .SearchInput")
|
||||
await app.client.waitForVisible(".PodLogControls .SearchInput input")
|
||||
// Search for semicolon
|
||||
await app.client.keys(":")
|
||||
await app.client.waitForVisible(".PodLogs .list span.active")
|
||||
// Click through controls
|
||||
await app.client.click(".PodLogControls .timestamps-icon")
|
||||
await app.client.click(".PodLogControls .undo-icon")
|
||||
})
|
||||
})
|
||||
|
||||
describe("cluster operations", () => {
|
||||
beforeEach(appStartAddCluster, 40000)
|
||||
|
||||
@ -439,7 +480,7 @@ describe("Lens integration tests", () => {
|
||||
|
||||
it(`creates a pod in ${TEST_NAMESPACE} namespace`, async () => {
|
||||
expect(clusterAdded).toBe(true)
|
||||
await app.client.click(".sidebar-nav #workloads span.link-text")
|
||||
await app.client.click(".sidebar-nav [data-test-id='workloads'] span.link-text")
|
||||
await app.client.waitUntilTextExists('a[href^="/pods"]', "Pods")
|
||||
await app.client.click('a[href^="/pods"]')
|
||||
await app.client.waitUntilTextExists("div.TableCell", "kube-apiserver")
|
||||
|
||||