mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Merge branch 'master' into extensions-api
This commit is contained in:
commit
de3849d22c
@ -1,69 +1,446 @@
|
|||||||
|
/*
|
||||||
|
Cluster tests are run if there is a pre-existing minikube cluster. Before running cluster tests the TEST_NAMESPACE
|
||||||
|
namespace is removed, if it exists, from the minikube cluster. Resources are created as part of the cluster tests in the
|
||||||
|
TEST_NAMESPACE namespace. This is done to minimize destructive impact of the cluster tests on an existing minikube
|
||||||
|
cluster and vice versa.
|
||||||
|
*/
|
||||||
import { Application } from "spectron"
|
import { Application } from "spectron"
|
||||||
import * as util from "../helpers/utils"
|
import * as util from "../helpers/utils"
|
||||||
import { spawnSync } from "child_process"
|
import { spawnSync } from "child_process"
|
||||||
|
|
||||||
jest.setTimeout(30000)
|
const describeif = (condition : boolean) => condition ? describe : describe.skip
|
||||||
|
const itif = (condition : boolean) => condition ? it : it.skip
|
||||||
|
|
||||||
const BACKSPACE = "\uE003"
|
jest.setTimeout(60000)
|
||||||
|
|
||||||
describe("app start", () => {
|
describe("Lens integration tests", () => {
|
||||||
|
const TEST_NAMESPACE = "integration-tests"
|
||||||
|
|
||||||
|
const BACKSPACE = "\uE003"
|
||||||
let app: Application
|
let app: Application
|
||||||
|
|
||||||
|
const appStart = async () => {
|
||||||
|
app = util.setup()
|
||||||
|
await app.start()
|
||||||
|
// Wait for splash screen to be closed
|
||||||
|
while (await app.client.getWindowCount() > 1);
|
||||||
|
await app.client.windowByIndex(0)
|
||||||
|
await app.client.waitUntilWindowLoaded()
|
||||||
|
}
|
||||||
|
|
||||||
const clickWhatsNew = async (app: Application) => {
|
const clickWhatsNew = async (app: Application) => {
|
||||||
await app.client.waitUntilTextExists("h1", "What's new")
|
await app.client.waitUntilTextExists("h1", "What's new")
|
||||||
await app.client.click("button.primary")
|
await app.client.click("button.primary")
|
||||||
await app.client.waitUntilTextExists("h1", "Welcome")
|
await app.client.waitUntilTextExists("h1", "Welcome")
|
||||||
}
|
}
|
||||||
|
|
||||||
const addMinikubeCluster = async (app: Application) => {
|
describe("app start", () => {
|
||||||
await app.client.click("div.add-cluster")
|
beforeAll(appStart, 20000)
|
||||||
await app.client.waitUntilTextExists("div", "Select kubeconfig file")
|
|
||||||
await app.client.click("button.primary")
|
|
||||||
}
|
|
||||||
|
|
||||||
const waitForMinikubeDashboard = async (app: Application) => {
|
afterAll(async () => {
|
||||||
await app.client.waitUntilTextExists("pre.kube-auth-out", "Authentication proxy started")
|
if (app && app.isRunning()) {
|
||||||
await app.client.getWindowCount()
|
return util.tearDown(app)
|
||||||
await app.client.waitForExist(`iframe[name="minikube"]`)
|
|
||||||
await app.client.frame("minikube")
|
|
||||||
await app.client.waitUntilTextExists("span.link-text", "Cluster")
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
beforeEach(async () => {
|
|
||||||
app = util.setup()
|
|
||||||
await app.start()
|
|
||||||
await app.client.waitUntilWindowLoaded()
|
|
||||||
// Wait for splash screen to be closed
|
|
||||||
while (await app.client.getWindowCount() > 1);
|
|
||||||
await app.client.windowByIndex(0)
|
|
||||||
await app.client.waitUntilWindowLoaded()
|
|
||||||
}, 20000)
|
|
||||||
|
|
||||||
it('shows "whats new"', async () => {
|
it('shows "whats new"', async () => {
|
||||||
await clickWhatsNew(app)
|
await clickWhatsNew(app)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('allows to add a cluster', async () => {
|
// Todo figure out how to access main menu to get these to work
|
||||||
const status = spawnSync("minikube status", { shell: true })
|
it.skip('shows "add cluster"', async () => {
|
||||||
|
await app.client.keys(['Shift', 'Meta', 'A'])
|
||||||
|
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')
|
||||||
|
})
|
||||||
|
|
||||||
|
it.skip('quits Lens"', async () => {
|
||||||
|
await app.client.keys(['Meta', 'Q'])
|
||||||
|
await app.client.keys('Meta')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const minikubeReady = (): boolean => {
|
||||||
|
// determine if minikube is running
|
||||||
|
let status = spawnSync("minikube status", { shell: true })
|
||||||
if (status.status !== 0) {
|
if (status.status !== 0) {
|
||||||
console.warn("minikube not running, skipping test")
|
console.warn("minikube not running")
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove TEST_NAMESPACE if it already exists
|
||||||
|
status = spawnSync(`minikube kubectl -- get namespace ${TEST_NAMESPACE}`, { shell: true })
|
||||||
|
if (status.status === 0) {
|
||||||
|
console.warn(`Removing existing ${TEST_NAMESPACE} namespace`)
|
||||||
|
status = spawnSync(`minikube kubectl -- delete namespace ${TEST_NAMESPACE}`, { shell: true })
|
||||||
|
if (status.status !== 0) {
|
||||||
|
console.warn(`Error removing ${TEST_NAMESPACE} namespace: ${status.stderr.toString()}`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
console.log(status.stdout.toString())
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
const ready = minikubeReady()
|
||||||
|
|
||||||
|
const addMinikubeCluster = async (app: Application) => {
|
||||||
|
await app.client.click("div.add-cluster")
|
||||||
|
await app.client.waitUntilTextExists("div", "Select kubeconfig file")
|
||||||
|
await app.client.click("div.Select__control") // show the context drop-down list
|
||||||
|
await app.client.waitUntilTextExists("div", "minikube")
|
||||||
|
if (!await app.client.$("button.primary").isEnabled()) {
|
||||||
|
await app.client.click("div.minikube") // select minikube context
|
||||||
|
} // else the only context, which must be 'minikube', is automatically selected
|
||||||
|
await app.client.click("div.Select__control") // hide the context drop-down list (it might be obscuring the Add cluster(s) button)
|
||||||
|
await app.client.click("button.primary") // add minikube cluster
|
||||||
|
}
|
||||||
|
|
||||||
|
const waitForMinikubeDashboard = async (app: Application) => {
|
||||||
|
await app.client.waitUntilTextExists("pre.kube-auth-out", "Authentication proxy started")
|
||||||
|
await app.client.waitForExist(`iframe[name="minikube"]`)
|
||||||
|
await app.client.frame("minikube")
|
||||||
|
await app.client.waitUntilTextExists("span.link-text", "Cluster")
|
||||||
|
}
|
||||||
|
|
||||||
|
describeif(ready)("cluster tests", () => {
|
||||||
|
let clusterAdded = false
|
||||||
|
|
||||||
|
const addCluster = async () => {
|
||||||
await clickWhatsNew(app)
|
await clickWhatsNew(app)
|
||||||
await addMinikubeCluster(app)
|
await addMinikubeCluster(app)
|
||||||
await waitForMinikubeDashboard(app)
|
await waitForMinikubeDashboard(app)
|
||||||
await app.client.click('a[href="/nodes"]')
|
await app.client.click('a[href="/nodes"]')
|
||||||
await app.client.waitUntilTextExists("div.TableCell", "Ready")
|
await app.client.waitUntilTextExists("div.TableCell", "Ready")
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("cluster add", () => {
|
||||||
|
beforeAll(appStart, 20000)
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
if (app && app.isRunning()) {
|
||||||
|
return util.tearDown(app)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('allows to create a pod', async () => {
|
it('allows to add a cluster', async () => {
|
||||||
const status = spawnSync("minikube status", { shell: true })
|
await addCluster()
|
||||||
if (status.status !== 0) {
|
clusterAdded = true
|
||||||
console.warn("minikube not running, skipping test")
|
})
|
||||||
return
|
})
|
||||||
|
|
||||||
|
const appStartAddCluster = async () => {
|
||||||
|
if (clusterAdded) {
|
||||||
|
await appStart()
|
||||||
|
await addCluster()
|
||||||
}
|
}
|
||||||
await clickWhatsNew(app)
|
}
|
||||||
await addMinikubeCluster(app)
|
|
||||||
await waitForMinikubeDashboard(app)
|
describe("cluster pages", () => {
|
||||||
|
|
||||||
|
beforeAll(appStartAddCluster, 40000)
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
if (app && app.isRunning()) {
|
||||||
|
return util.tearDown(app)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const tests : {
|
||||||
|
drawer?: string
|
||||||
|
drawerId?: string
|
||||||
|
pages: {
|
||||||
|
name: string,
|
||||||
|
href: string,
|
||||||
|
expectedSelector: string,
|
||||||
|
expectedText: string
|
||||||
|
}[]
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
drawer: "",
|
||||||
|
drawerId: "",
|
||||||
|
pages: [ {
|
||||||
|
name: "Cluster",
|
||||||
|
href: "cluster",
|
||||||
|
expectedSelector: "div.ClusterNoMetrics p",
|
||||||
|
expectedText: "Metrics are not available due"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "",
|
||||||
|
drawerId: "",
|
||||||
|
pages: [ {
|
||||||
|
name: "Nodes",
|
||||||
|
href: "nodes",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Nodes"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "Workloads",
|
||||||
|
drawerId: "workloads",
|
||||||
|
pages: [ {
|
||||||
|
name: "Overview",
|
||||||
|
href: "workloads",
|
||||||
|
expectedSelector: "h5.box",
|
||||||
|
expectedText: "Overview"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Pods",
|
||||||
|
href: "pods",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Pods"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Deployments",
|
||||||
|
href: "deployments",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Deployments"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "DaemonSets",
|
||||||
|
href: "daemonsets",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Daemon Sets"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "StatefulSets",
|
||||||
|
href: "statefulsets",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Stateful Sets"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Jobs",
|
||||||
|
href: "jobs",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Jobs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "CronJobs",
|
||||||
|
href: "cronjobs",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Cron Jobs"
|
||||||
|
} ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "Configuration",
|
||||||
|
drawerId: "config",
|
||||||
|
pages: [ {
|
||||||
|
name: "ConfigMaps",
|
||||||
|
href: "configmaps",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Config Maps"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Secrets",
|
||||||
|
href: "secrets",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Secrets"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Resource Quotas",
|
||||||
|
href: "resourcequotas",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Resource Quotas"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "HPA",
|
||||||
|
href: "hpa",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Horizontal Pod Autoscalers"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Pod Disruption Budgets",
|
||||||
|
href: "poddisruptionbudgets",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Pod Disruption Budgets"
|
||||||
|
} ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "Network",
|
||||||
|
drawerId: "networks",
|
||||||
|
pages: [ {
|
||||||
|
name: "Services",
|
||||||
|
href: "services",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Services"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Endpoints",
|
||||||
|
href: "endpoints",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Endpoints"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Ingresses",
|
||||||
|
href: "ingresses",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Ingresses"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Network Policies",
|
||||||
|
href: "network-policies",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Network Policies"
|
||||||
|
} ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "Storage",
|
||||||
|
drawerId: "storage",
|
||||||
|
pages: [ {
|
||||||
|
name: "Persistent Volume Claims",
|
||||||
|
href: "persistent-volume-claims",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Persistent Volume Claims"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Persistent Volumes",
|
||||||
|
href: "persistent-volumes",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Persistent Volumes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Storage Classes",
|
||||||
|
href: "storage-classes",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Storage Classes"
|
||||||
|
} ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "",
|
||||||
|
drawerId: "",
|
||||||
|
pages: [ {
|
||||||
|
name: "Namespaces",
|
||||||
|
href: "namespaces",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Namespaces"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "",
|
||||||
|
drawerId: "",
|
||||||
|
pages: [ {
|
||||||
|
name: "Events",
|
||||||
|
href: "events",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Events"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "Apps",
|
||||||
|
drawerId: "apps",
|
||||||
|
pages: [ {
|
||||||
|
name: "Charts",
|
||||||
|
href: "apps/charts",
|
||||||
|
expectedSelector: "div.HelmCharts input",
|
||||||
|
expectedText: ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Releases",
|
||||||
|
href: "apps/releases",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Releases"
|
||||||
|
} ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "Access Control",
|
||||||
|
drawerId: "users",
|
||||||
|
pages: [ {
|
||||||
|
name: "Service Accounts",
|
||||||
|
href: "service-accounts",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Service Accounts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Role Bindings",
|
||||||
|
href: "role-bindings",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Role Bindings"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Roles",
|
||||||
|
href: "roles",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Roles"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Pod Security Policies",
|
||||||
|
href: "pod-security-policies",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Pod Security Policies"
|
||||||
|
} ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "Custom Resources",
|
||||||
|
drawerId: "custom-resources",
|
||||||
|
pages: [ {
|
||||||
|
name: "Definitions",
|
||||||
|
href: "crd/definitions",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Custom Resources"
|
||||||
|
} ]
|
||||||
|
},
|
||||||
|
];
|
||||||
|
tests.forEach(({ drawer = "", drawerId = "", pages }) => {
|
||||||
|
if (drawer !== "") {
|
||||||
|
it(`shows ${drawer} drawer`, async () => {
|
||||||
|
expect(clusterAdded).toBe(true)
|
||||||
|
await app.client.click(`.sidebar-nav #${drawerId} span.link-text`)
|
||||||
|
await app.client.waitUntilTextExists(`a[href="/${pages[0].href}"]`, pages[0].name)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pages.forEach(({name, href, expectedSelector, expectedText}) => {
|
||||||
|
it(`shows ${drawer}->${name} page`, async () => {
|
||||||
|
expect(clusterAdded).toBe(true)
|
||||||
|
await app.client.click(`a[href="/${href}"]`)
|
||||||
|
await app.client.waitUntilTextExists(expectedSelector, expectedText)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
if (drawer !== "") {
|
||||||
|
// hide the drawer
|
||||||
|
it(`hides ${drawer} drawer`, async () => {
|
||||||
|
expect(clusterAdded).toBe(true)
|
||||||
|
await app.client.click(`.sidebar-nav #${drawerId} span.link-text`)
|
||||||
|
await expect(app.client.waitUntilTextExists(`a[href="/${pages[0].href}"]`, pages[0].name, 100)).rejects.toThrow()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("cluster operations", () => {
|
||||||
|
beforeEach(appStartAddCluster, 40000)
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
if (app && app.isRunning()) {
|
||||||
|
return util.tearDown(app)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows default namespace', async () => {
|
||||||
|
expect(clusterAdded).toBe(true)
|
||||||
|
await app.client.click('a[href="/namespaces"]')
|
||||||
|
await app.client.waitUntilTextExists("div.TableCell", "default")
|
||||||
|
await app.client.waitUntilTextExists("div.TableCell", "kube-system")
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`creates ${TEST_NAMESPACE} namespace`, async () => {
|
||||||
|
expect(clusterAdded).toBe(true)
|
||||||
|
await app.client.click('a[href="/namespaces"]')
|
||||||
|
await app.client.waitUntilTextExists("div.TableCell", "default")
|
||||||
|
await app.client.waitUntilTextExists("div.TableCell", "kube-system")
|
||||||
|
await app.client.click("button.add-button")
|
||||||
|
await app.client.waitUntilTextExists("div.AddNamespaceDialog", "Create Namespace")
|
||||||
|
await app.client.keys(`${TEST_NAMESPACE}\n`)
|
||||||
|
await app.client.waitForExist(`.name=${TEST_NAMESPACE}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
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 #workloads span.link-text")
|
||||||
await app.client.waitUntilTextExists('a[href="/pods"]', "Pods")
|
await app.client.waitUntilTextExists('a[href="/pods"]', "Pods")
|
||||||
await app.client.click('a[href="/pods"]')
|
await app.client.click('a[href="/pods"]')
|
||||||
@ -76,24 +453,21 @@ describe("app start", () => {
|
|||||||
await app.client.keys("apiVersion: v1\n")
|
await app.client.keys("apiVersion: v1\n")
|
||||||
await app.client.keys("kind: Pod\n")
|
await app.client.keys("kind: Pod\n")
|
||||||
await app.client.keys("metadata:\n")
|
await app.client.keys("metadata:\n")
|
||||||
await app.client.keys(" name: nginx\n")
|
await app.client.keys(" name: nginx-create-pod-test\n")
|
||||||
|
await app.client.keys(`namespace: ${TEST_NAMESPACE}\n`)
|
||||||
await app.client.keys(BACKSPACE + "spec:\n")
|
await app.client.keys(BACKSPACE + "spec:\n")
|
||||||
await app.client.keys(" containers:\n")
|
await app.client.keys(" containers:\n")
|
||||||
await app.client.keys("- name: nginx\n")
|
await app.client.keys("- name: nginx-create-pod-test\n")
|
||||||
await app.client.keys(" image: nginx:alpine\n")
|
await app.client.keys(" image: nginx:alpine\n")
|
||||||
// Create deployent
|
// Create deployment
|
||||||
await app.client.waitForEnabled("button.Button=Create & Close")
|
await app.client.waitForEnabled("button.Button=Create & Close")
|
||||||
await app.client.click("button.Button=Create & Close")
|
await app.client.click("button.Button=Create & Close")
|
||||||
// Wait until first bits of pod appears on dashboard
|
// Wait until first bits of pod appears on dashboard
|
||||||
await app.client.waitForExist(".name=nginx")
|
await app.client.waitForExist(".name=nginx-create-pod-test")
|
||||||
// Open pod details
|
// Open pod details
|
||||||
await app.client.click(".name=nginx")
|
await app.client.click(".name=nginx-create-pod-test")
|
||||||
await app.client.waitUntilTextExists("div.drawer-title-text", "Pod: nginx")
|
await app.client.waitUntilTextExists("div.drawer-title-text", "Pod: nginx-create-pod-test")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
|
||||||
if (app && app.isRunning()) {
|
|
||||||
return util.tearDown(app)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -25,7 +25,7 @@ msgstr ""
|
|||||||
msgid "(as a percentage of request)"
|
msgid "(as a percentage of request)"
|
||||||
msgstr "(as a percentage of request)"
|
msgstr "(as a percentage of request)"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:108
|
#: src/renderer/components/+workspaces/workspaces.tsx:121
|
||||||
msgid "(current)"
|
msgid "(current)"
|
||||||
msgstr "(current)"
|
msgstr "(current)"
|
||||||
|
|
||||||
@ -57,11 +57,11 @@ msgstr "<0>{0}</0> successfully created"
|
|||||||
#~ msgid "A HTTP proxy server URL (format: http://<address>:<port>)"
|
#~ msgid "A HTTP proxy server URL (format: http://<address>:<port>)"
|
||||||
#~ msgstr "A HTTP proxy server URL (format: http://<address>:<port>)"
|
#~ msgstr "A HTTP proxy server URL (format: http://<address>:<port>)"
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:40
|
#: src/renderer/components/input/input.validators.ts:46
|
||||||
msgid "A System Name must be lowercase DNS labels separated by dots. DNS labels are alphanumerics and dashes enclosed by alphanumerics."
|
msgid "A System Name must be lowercase DNS labels separated by dots. DNS labels are alphanumerics and dashes enclosed by alphanumerics."
|
||||||
msgstr "A System Name must be lowercase DNS labels separated by dots. DNS labels are alphanumerics and dashes enclosed by alphanumerics."
|
msgstr "A System Name must be lowercase DNS labels separated by dots. DNS labels are alphanumerics and dashes enclosed by alphanumerics."
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:84
|
#: src/renderer/components/+workspaces/workspaces.tsx:93
|
||||||
msgid "A single workspaces contains a list of clusters and their full configuration."
|
msgid "A single workspaces contains a list of clusters and their full configuration."
|
||||||
msgstr "A single workspaces contains a list of clusters and their full configuration."
|
msgstr "A single workspaces contains a list of clusters and their full configuration."
|
||||||
|
|
||||||
@ -87,8 +87,8 @@ msgstr "Account Name"
|
|||||||
msgid "Active"
|
msgid "Active"
|
||||||
msgstr "Active"
|
msgstr "Active"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:303
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:288
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:118
|
#: src/renderer/components/cluster-manager/clusters-menu.tsx:130
|
||||||
msgid "Add Cluster"
|
msgid "Add Cluster"
|
||||||
msgstr "Add Cluster"
|
msgstr "Add Cluster"
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ msgstr "Add Namespace"
|
|||||||
msgid "Add RoleBinding"
|
msgid "Add RoleBinding"
|
||||||
msgstr "Add RoleBinding"
|
msgstr "Add RoleBinding"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:125
|
#: src/renderer/components/+workspaces/workspaces.tsx:138
|
||||||
msgid "Add Workspace"
|
msgid "Add Workspace"
|
||||||
msgstr "Add Workspace"
|
msgstr "Add Workspace"
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ msgstr "Add bindings to {name}"
|
|||||||
#~ msgid "Add cluster"
|
#~ msgid "Add cluster"
|
||||||
#~ msgstr "Add cluster"
|
#~ msgstr "Add cluster"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:320
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:305
|
||||||
msgid "Add cluster(s)"
|
msgid "Add cluster(s)"
|
||||||
msgstr "Add cluster(s)"
|
msgstr "Add cluster(s)"
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ msgstr "Add field"
|
|||||||
#~ msgid "Adding clusters: <0>{0}</0>"
|
#~ msgid "Adding clusters: <0>{0}</0>"
|
||||||
#~ msgstr "Adding clusters: <0>{0}</0>"
|
#~ msgstr "Adding clusters: <0>{0}</0>"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:103
|
#: src/renderer/components/+preferences/preferences.tsx:111
|
||||||
msgid "Adding helm branch <0>{0}</0> has failed: {1}"
|
msgid "Adding helm branch <0>{0}</0> has failed: {1}"
|
||||||
msgstr "Adding helm branch <0>{0}</0> has failed: {1}"
|
msgstr "Adding helm branch <0>{0}</0> has failed: {1}"
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ msgstr "Affinities"
|
|||||||
msgid "Age"
|
msgid "Age"
|
||||||
msgstr "Age"
|
msgstr "Age"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:64
|
#: src/renderer/components/+workspaces/workspaces.tsx:65
|
||||||
msgid "All clusters within workspace will be cleared as well"
|
msgid "All clusters within workspace will be cleared as well"
|
||||||
msgstr "All clusters within workspace will be cleared as well"
|
msgstr "All clusters within workspace will be cleared as well"
|
||||||
|
|
||||||
@ -219,11 +219,11 @@ msgstr "Allocatable"
|
|||||||
msgid "Allow Privilege Escalation"
|
msgid "Allow Privilege Escalation"
|
||||||
msgstr "Allow Privilege Escalation"
|
msgstr "Allow Privilege Escalation"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:162
|
#: src/renderer/components/+preferences/preferences.tsx:169
|
||||||
msgid "Allow telemetry & usage tracking"
|
msgid "Allow telemetry & usage tracking"
|
||||||
msgstr "Allow telemetry & usage tracking"
|
msgstr "Allow telemetry & usage tracking"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:154
|
#: src/renderer/components/+preferences/preferences.tsx:161
|
||||||
msgid "Allow untrusted Certificate Authorities"
|
msgid "Allow untrusted Certificate Authorities"
|
||||||
msgstr "Allow untrusted Certificate Authorities"
|
msgstr "Allow untrusted Certificate Authorities"
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ msgstr "Applying.."
|
|||||||
msgid "Apps"
|
msgid "Apps"
|
||||||
msgstr "Apps"
|
msgstr "Apps"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:61
|
#: src/renderer/components/+workspaces/workspaces.tsx:62
|
||||||
msgid "Are you sure you want remove workspace <0>{0}</0>?"
|
msgid "Are you sure you want remove workspace <0>{0}</0>?"
|
||||||
msgstr "Are you sure you want remove workspace <0>{0}</0>?"
|
msgstr "Are you sure you want remove workspace <0>{0}</0>?"
|
||||||
|
|
||||||
@ -293,7 +293,7 @@ msgstr "Are you sure you want to drain <0>{nodeName}</0>?"
|
|||||||
msgid "Arguments"
|
msgid "Arguments"
|
||||||
msgstr "Arguments"
|
msgstr "Arguments"
|
||||||
|
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:108
|
#: src/renderer/components/+landing-page/landing-page.tsx:27
|
||||||
msgid "Associate clusters and choose the ones you want to access via quick launch menu by clicking the + button."
|
msgid "Associate clusters and choose the ones you want to access via quick launch menu by clicking the + button."
|
||||||
msgstr "Associate clusters and choose the ones you want to access via quick launch menu by clicking the + button."
|
msgstr "Associate clusters and choose the ones you want to access via quick launch menu by clicking the + button."
|
||||||
|
|
||||||
@ -323,7 +323,7 @@ msgstr "Binding targets"
|
|||||||
msgid "Bindings"
|
msgid "Bindings"
|
||||||
msgstr "Bindings"
|
msgstr "Bindings"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:251
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:236
|
||||||
msgid "Browse"
|
msgid "Browse"
|
||||||
msgstr "Browse"
|
msgstr "Browse"
|
||||||
|
|
||||||
@ -402,7 +402,7 @@ msgstr "CPU requests"
|
|||||||
msgid "CPU:"
|
msgid "CPU:"
|
||||||
msgstr "CPU:"
|
msgstr "CPU:"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:119
|
#: src/renderer/components/+workspaces/workspaces.tsx:133
|
||||||
#: src/renderer/components/confirm-dialog/confirm-dialog.tsx:44
|
#: src/renderer/components/confirm-dialog/confirm-dialog.tsx:44
|
||||||
#: src/renderer/components/dock/info-panel.tsx:97
|
#: src/renderer/components/dock/info-panel.tsx:97
|
||||||
#: src/renderer/components/wizard/wizard.tsx:130
|
#: src/renderer/components/wizard/wizard.tsx:130
|
||||||
@ -422,7 +422,7 @@ msgstr "Cancel"
|
|||||||
msgid "Capacity"
|
msgid "Capacity"
|
||||||
msgstr "Capacity"
|
msgstr "Capacity"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:153
|
#: src/renderer/components/+preferences/preferences.tsx:160
|
||||||
msgid "Certificate Trust"
|
msgid "Certificate Trust"
|
||||||
msgstr "Certificate Trust"
|
msgstr "Certificate Trust"
|
||||||
|
|
||||||
@ -501,7 +501,7 @@ msgstr "Cluster IP"
|
|||||||
msgid "Cluster Issuers"
|
msgid "Cluster Issuers"
|
||||||
msgstr "Cluster Issuers"
|
msgstr "Cluster Issuers"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:126
|
#: src/renderer/components/+preferences/preferences.tsx:134
|
||||||
msgid "Color Theme"
|
msgid "Color Theme"
|
||||||
msgstr "Color Theme"
|
msgstr "Color Theme"
|
||||||
|
|
||||||
@ -712,7 +712,6 @@ msgid "Cron Jobs"
|
|||||||
msgstr "Cron Jobs"
|
msgstr "Cron Jobs"
|
||||||
|
|
||||||
#: src/renderer/components/+workloads/workloads.tsx:77
|
#: src/renderer/components/+workloads/workloads.tsx:77
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:67
|
|
||||||
msgid "CronJobs"
|
msgid "CronJobs"
|
||||||
msgstr "CronJobs"
|
msgstr "CronJobs"
|
||||||
|
|
||||||
@ -759,7 +758,6 @@ msgid "Daemon Sets"
|
|||||||
msgstr "Daemon Sets"
|
msgstr "Daemon Sets"
|
||||||
|
|
||||||
#: src/renderer/components/+workloads/workloads.tsx:53
|
#: src/renderer/components/+workloads/workloads.tsx:53
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:57
|
|
||||||
msgid "DaemonSets"
|
msgid "DaemonSets"
|
||||||
msgstr "DaemonSets"
|
msgstr "DaemonSets"
|
||||||
|
|
||||||
@ -784,11 +782,15 @@ msgstr "Default Add Capabilities"
|
|||||||
msgid "Default Runtime Class Name"
|
msgid "Default Runtime Class Name"
|
||||||
msgstr "Default Runtime Class Name"
|
msgstr "Default Runtime Class Name"
|
||||||
|
|
||||||
|
#: src/renderer/components/+preferences/kubectl-binaries.tsx:30
|
||||||
|
msgid "Default:"
|
||||||
|
msgstr "Default:"
|
||||||
|
|
||||||
#: src/renderer/components/+custom-resources/custom-resources.tsx:22
|
#: src/renderer/components/+custom-resources/custom-resources.tsx:22
|
||||||
msgid "Definitions"
|
msgid "Definitions"
|
||||||
msgstr "Definitions"
|
msgstr "Definitions"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:113
|
#: src/renderer/components/+workspaces/workspaces.tsx:126
|
||||||
#: src/renderer/components/menu/menu-actions.tsx:84
|
#: src/renderer/components/menu/menu-actions.tsx:84
|
||||||
msgid "Delete"
|
msgid "Delete"
|
||||||
msgstr "Delete"
|
msgstr "Delete"
|
||||||
@ -799,12 +801,11 @@ msgstr "Deploy Revisions"
|
|||||||
|
|
||||||
#: src/renderer/components/+workloads/workloads.tsx:45
|
#: src/renderer/components/+workloads/workloads.tsx:45
|
||||||
#: src/renderer/components/+workloads-deployments/deployments.tsx:57
|
#: src/renderer/components/+workloads-deployments/deployments.tsx:57
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:47
|
|
||||||
msgid "Deployments"
|
msgid "Deployments"
|
||||||
msgstr "Deployments"
|
msgstr "Deployments"
|
||||||
|
|
||||||
#: src/renderer/components/+apps-helm-charts/helm-charts.tsx:65
|
#: src/renderer/components/+apps-helm-charts/helm-charts.tsx:65
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:118
|
#: src/renderer/components/+workspaces/workspaces.tsx:131
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Description"
|
msgstr "Description"
|
||||||
|
|
||||||
@ -817,7 +818,7 @@ msgstr "Desired Healthy"
|
|||||||
msgid "Desired number of replicas"
|
msgid "Desired number of replicas"
|
||||||
msgstr "Desired number of replicas"
|
msgstr "Desired number of replicas"
|
||||||
|
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:64
|
#: src/renderer/components/cluster-manager/clusters-menu.tsx:65
|
||||||
msgid "Disconnect"
|
msgid "Disconnect"
|
||||||
msgstr "Disconnect"
|
msgstr "Disconnect"
|
||||||
|
|
||||||
@ -831,7 +832,7 @@ msgstr "Disk"
|
|||||||
msgid "Disk:"
|
msgid "Disk:"
|
||||||
msgstr "Disk:"
|
msgstr "Disk:"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:158
|
#: src/renderer/components/+preferences/preferences.tsx:165
|
||||||
msgid "Does not affect cluster communications!"
|
msgid "Does not affect cluster communications!"
|
||||||
msgstr "Does not affect cluster communications!"
|
msgstr "Does not affect cluster communications!"
|
||||||
|
|
||||||
@ -840,14 +841,22 @@ msgid "Domains"
|
|||||||
msgstr "Domains"
|
msgstr "Domains"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:129
|
#: src/renderer/components/+preferences/preferences.tsx:129
|
||||||
msgid "Download Mirror"
|
#~ msgid "Download Mirror"
|
||||||
msgstr "Download Mirror"
|
#~ msgstr "Download Mirror"
|
||||||
|
|
||||||
#: src/renderer/components/kubeconfig-dialog/kubeconfig-dialog.tsx:90
|
#: src/renderer/components/kubeconfig-dialog/kubeconfig-dialog.tsx:90
|
||||||
msgid "Download file"
|
msgid "Download file"
|
||||||
msgstr "Download file"
|
msgstr "Download file"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:130
|
#: src/renderer/components/+preferences/kubectl-binaries.tsx:39
|
||||||
|
msgid "Download kubectl binaries"
|
||||||
|
msgstr "Download kubectl binaries"
|
||||||
|
|
||||||
|
#: src/renderer/components/+preferences/kubectl-binaries.tsx:37
|
||||||
|
msgid "Download kubectl binaries matching to Kubernetes cluster verison."
|
||||||
|
msgstr "Download kubectl binaries matching to Kubernetes cluster verison."
|
||||||
|
|
||||||
|
#: src/renderer/components/+preferences/kubectl-binaries.tsx:41
|
||||||
msgid "Download mirror for kubectl"
|
msgid "Download mirror for kubectl"
|
||||||
msgstr "Download mirror for kubectl"
|
msgstr "Download mirror for kubectl"
|
||||||
|
|
||||||
@ -873,7 +882,7 @@ msgstr "Duration"
|
|||||||
msgid "E-mail"
|
msgid "E-mail"
|
||||||
msgstr "E-mail"
|
msgstr "E-mail"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:112
|
#: src/renderer/components/+workspaces/workspaces.tsx:125
|
||||||
#: src/renderer/components/menu/menu-actions.tsx:80
|
#: src/renderer/components/menu/menu-actions.tsx:80
|
||||||
#: src/renderer/components/menu/menu-actions.tsx:81
|
#: src/renderer/components/menu/menu-actions.tsx:81
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@ -1000,7 +1009,7 @@ msgstr "From <0>{from}</0> to <1>{to}</1>"
|
|||||||
msgid "Fs Group"
|
msgid "Fs Group"
|
||||||
msgstr "Fs Group"
|
msgstr "Fs Group"
|
||||||
|
|
||||||
#: src/renderer/components/+landing-page/landing-page.tsx:23
|
#: src/renderer/components/+landing-page/landing-page.tsx:37
|
||||||
msgid "Get started by associating one or more clusters to Lens."
|
msgid "Get started by associating one or more clusters to Lens."
|
||||||
msgstr "Get started by associating one or more clusters to Lens."
|
msgstr "Get started by associating one or more clusters to Lens."
|
||||||
|
|
||||||
@ -1022,7 +1031,7 @@ msgstr "Groups"
|
|||||||
msgid "HPA"
|
msgid "HPA"
|
||||||
msgstr "HPA"
|
msgstr "HPA"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:147
|
#: src/renderer/components/+preferences/preferences.tsx:137
|
||||||
msgid "HTTP Proxy"
|
msgid "HTTP Proxy"
|
||||||
msgstr "HTTP Proxy"
|
msgstr "HTTP Proxy"
|
||||||
|
|
||||||
@ -1030,7 +1039,7 @@ msgstr "HTTP Proxy"
|
|||||||
#~ msgid "HTTP Proxy server. Used for communicating with Kubernetes API."
|
#~ msgid "HTTP Proxy server. Used for communicating with Kubernetes API."
|
||||||
#~ msgstr "HTTP Proxy server. Used for communicating with Kubernetes API."
|
#~ msgstr "HTTP Proxy server. Used for communicating with Kubernetes API."
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:132
|
#: src/renderer/components/+preferences/preferences.tsx:145
|
||||||
msgid "Helm"
|
msgid "Helm"
|
||||||
msgstr "Helm"
|
msgstr "Helm"
|
||||||
|
|
||||||
@ -1050,7 +1059,7 @@ msgstr "Helm Install: {repo}/{name}"
|
|||||||
msgid "Helm Upgrade: {0}"
|
msgid "Helm Upgrade: {0}"
|
||||||
msgstr "Helm Upgrade: {0}"
|
msgstr "Helm Upgrade: {0}"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:47
|
#: src/renderer/components/+preferences/preferences.tsx:51
|
||||||
msgid "Helm branch <0>{0}</0> already in use"
|
msgid "Helm branch <0>{0}</0> already in use"
|
||||||
msgstr "Helm branch <0>{0}</0> already in use"
|
msgstr "Helm branch <0>{0}</0> already in use"
|
||||||
|
|
||||||
@ -1157,11 +1166,11 @@ msgstr "Installation complete!"
|
|||||||
msgid "Installing..."
|
msgid "Installing..."
|
||||||
msgstr "Installing..."
|
msgstr "Installing..."
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:44
|
#: src/renderer/components/input/input.validators.ts:50
|
||||||
msgid "Invalid account ID"
|
msgid "Invalid account ID"
|
||||||
msgstr "Invalid account ID"
|
msgstr "Invalid account ID"
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:15
|
#: src/renderer/components/input/input.validators.ts:16
|
||||||
msgid "Invalid number"
|
msgid "Invalid number"
|
||||||
msgstr "Invalid number"
|
msgstr "Invalid number"
|
||||||
|
|
||||||
@ -1197,7 +1206,6 @@ msgstr "Job name"
|
|||||||
#: src/renderer/components/+workloads/workloads.tsx:69
|
#: src/renderer/components/+workloads/workloads.tsx:69
|
||||||
#: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:62
|
#: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:62
|
||||||
#: src/renderer/components/+workloads-jobs/jobs.tsx:36
|
#: src/renderer/components/+workloads-jobs/jobs.tsx:36
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:62
|
|
||||||
msgid "Jobs"
|
msgid "Jobs"
|
||||||
msgstr "Jobs"
|
msgstr "Jobs"
|
||||||
|
|
||||||
@ -1241,6 +1249,10 @@ msgstr "Kubeconfig"
|
|||||||
msgid "Kubeconfig File"
|
msgid "Kubeconfig File"
|
||||||
msgstr "Kubeconfig File"
|
msgstr "Kubeconfig File"
|
||||||
|
|
||||||
|
#: src/renderer/components/+preferences/kubectl-binaries.tsx:35
|
||||||
|
msgid "Kubectl Binary"
|
||||||
|
msgstr "Kubectl Binary"
|
||||||
|
|
||||||
#: src/renderer/components/+nodes/node-details.tsx:98
|
#: src/renderer/components/+nodes/node-details.tsx:98
|
||||||
msgid "Kubelet version"
|
msgid "Kubelet version"
|
||||||
msgstr "Kubelet version"
|
msgstr "Kubelet version"
|
||||||
@ -1357,7 +1369,7 @@ msgstr "Max Pods"
|
|||||||
msgid "Max Unavailable"
|
msgid "Max Unavailable"
|
||||||
msgstr "Max Unavailable"
|
msgstr "Max Unavailable"
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:35
|
#: src/renderer/components/input/input.validators.ts:41
|
||||||
msgid "Maximum length is {maxLength}"
|
msgid "Maximum length is {maxLength}"
|
||||||
msgstr "Maximum length is {maxLength}"
|
msgstr "Maximum length is {maxLength}"
|
||||||
|
|
||||||
@ -1433,7 +1445,7 @@ msgstr "Min Pods"
|
|||||||
msgid "Minimize"
|
msgid "Minimize"
|
||||||
msgstr "Minimize"
|
msgstr "Minimize"
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:30
|
#: src/renderer/components/input/input.validators.ts:36
|
||||||
msgid "Minimum length is {minLength}"
|
msgid "Minimum length is {minLength}"
|
||||||
msgstr "Minimum length is {minLength}"
|
msgstr "Minimum length is {minLength}"
|
||||||
|
|
||||||
@ -1497,7 +1509,7 @@ msgstr "Mounts"
|
|||||||
#: src/renderer/components/+workloads-pods/pods.tsx:74
|
#: src/renderer/components/+workloads-pods/pods.tsx:74
|
||||||
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:50
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:50
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulsets.tsx:40
|
#: src/renderer/components/+workloads-statefulsets/statefulsets.tsx:40
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:117
|
#: src/renderer/components/+workspaces/workspaces.tsx:130
|
||||||
#: src/renderer/components/dock/edit-resource.tsx:90
|
#: src/renderer/components/dock/edit-resource.tsx:90
|
||||||
#: src/renderer/components/kube-object/kube-object-meta.tsx:20
|
#: src/renderer/components/kube-object/kube-object-meta.tsx:20
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
@ -1565,7 +1577,7 @@ msgstr "Namespaces"
|
|||||||
msgid "Namespaces: {0}"
|
msgid "Namespaces: {0}"
|
||||||
msgstr "Namespaces: {0}"
|
msgstr "Namespaces: {0}"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:157
|
#: src/renderer/components/+preferences/preferences.tsx:164
|
||||||
msgid "Needed with some corporate proxies that do certificate re-writing."
|
msgid "Needed with some corporate proxies that do certificate re-writing."
|
||||||
msgstr "Needed with some corporate proxies that do certificate re-writing."
|
msgstr "Needed with some corporate proxies that do certificate re-writing."
|
||||||
|
|
||||||
@ -1626,7 +1638,7 @@ msgstr "No Nodes Available."
|
|||||||
#~ msgid "No contexts available or they already added"
|
#~ msgid "No contexts available or they already added"
|
||||||
#~ msgstr "No contexts available or they already added"
|
#~ msgstr "No contexts available or they already added"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:275
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:260
|
||||||
msgid "No contexts available or they have been added already"
|
msgid "No contexts available or they have been added already"
|
||||||
msgstr "No contexts available or they have been added already"
|
msgstr "No contexts available or they have been added already"
|
||||||
|
|
||||||
@ -1742,7 +1754,7 @@ msgid "Organization"
|
|||||||
msgstr "Organization"
|
msgstr "Organization"
|
||||||
|
|
||||||
#: src/renderer/components/+workloads/workloads.tsx:29
|
#: src/renderer/components/+workloads/workloads.tsx:29
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:35
|
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:45
|
||||||
msgid "Overview"
|
msgid "Overview"
|
||||||
msgstr "Overview"
|
msgstr "Overview"
|
||||||
|
|
||||||
@ -1758,7 +1770,7 @@ msgstr "Parallelism"
|
|||||||
msgid "Parameters"
|
msgid "Parameters"
|
||||||
msgstr "Parameters"
|
msgstr "Parameters"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:245
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:230
|
||||||
msgid "Paste as text"
|
msgid "Paste as text"
|
||||||
msgstr "Paste as text"
|
msgstr "Paste as text"
|
||||||
|
|
||||||
@ -1848,7 +1860,6 @@ msgstr "Pod shell"
|
|||||||
#: src/renderer/components/+workloads/workloads.tsx:37
|
#: src/renderer/components/+workloads/workloads.tsx:37
|
||||||
#: src/renderer/components/+workloads-daemonsets/daemonsets.tsx:47
|
#: src/renderer/components/+workloads-daemonsets/daemonsets.tsx:47
|
||||||
#: src/renderer/components/+workloads-deployments/deployments.tsx:60
|
#: src/renderer/components/+workloads-deployments/deployments.tsx:60
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:42
|
|
||||||
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:89
|
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:89
|
||||||
#: src/renderer/components/+workloads-pods/pods.tsx:73
|
#: src/renderer/components/+workloads-pods/pods.tsx:73
|
||||||
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:52
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:52
|
||||||
@ -1899,7 +1910,7 @@ msgstr "Privileged"
|
|||||||
#~ msgid "Pro-Tip: paste kubeconfig to collect available contexts"
|
#~ msgid "Pro-Tip: paste kubeconfig to collect available contexts"
|
||||||
#~ msgstr "Pro-Tip: paste kubeconfig to collect available contexts"
|
#~ msgstr "Pro-Tip: paste kubeconfig to collect available contexts"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:263
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:248
|
||||||
msgid "Pro-Tip: paste kubeconfig to get available contexts"
|
msgid "Pro-Tip: paste kubeconfig to get available contexts"
|
||||||
msgstr "Pro-Tip: paste kubeconfig to get available contexts"
|
msgstr "Pro-Tip: paste kubeconfig to get available contexts"
|
||||||
|
|
||||||
@ -1907,7 +1918,7 @@ msgstr "Pro-Tip: paste kubeconfig to get available contexts"
|
|||||||
#~ msgid "Pro-Tip: paste kubeconfig to parse available contexts"
|
#~ msgid "Pro-Tip: paste kubeconfig to parse available contexts"
|
||||||
#~ msgstr "Pro-Tip: paste kubeconfig to parse available contexts"
|
#~ msgstr "Pro-Tip: paste kubeconfig to parse available contexts"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:254
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:239
|
||||||
msgid "Pro-Tip: you can also drag-n-drop kubeconfig file to this area"
|
msgid "Pro-Tip: you can also drag-n-drop kubeconfig file to this area"
|
||||||
msgstr "Pro-Tip: you can also drag-n-drop kubeconfig file to this area"
|
msgstr "Pro-Tip: you can also drag-n-drop kubeconfig file to this area"
|
||||||
|
|
||||||
@ -1924,11 +1935,11 @@ msgstr "Pro-Tip: you can also drag-n-drop kubeconfig file to this area"
|
|||||||
msgid "Provisioner"
|
msgid "Provisioner"
|
||||||
msgstr "Provisioner"
|
msgstr "Provisioner"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:150
|
#: src/renderer/components/+preferences/preferences.tsx:140
|
||||||
msgid "Proxy is used only for non-cluster communication."
|
msgid "Proxy is used only for non-cluster communication."
|
||||||
msgstr "Proxy is used only for non-cluster communication."
|
msgstr "Proxy is used only for non-cluster communication."
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:308
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:293
|
||||||
msgid "Proxy settings"
|
msgid "Proxy settings"
|
||||||
msgstr "Proxy settings"
|
msgstr "Proxy settings"
|
||||||
|
|
||||||
@ -2008,10 +2019,10 @@ msgstr "Release: {0}"
|
|||||||
msgid "Releases"
|
msgid "Releases"
|
||||||
msgstr "Releases"
|
msgstr "Releases"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:139
|
#: src/renderer/components/+preferences/preferences.tsx:152
|
||||||
#: src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx:60
|
#: src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx:60
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:74
|
#: src/renderer/components/cluster-manager/clusters-menu.tsx:76
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:80
|
#: src/renderer/components/cluster-manager/clusters-menu.tsx:82
|
||||||
#: src/renderer/components/item-object-list/item-list-layout.tsx:179
|
#: src/renderer/components/item-object-list/item-list-layout.tsx:179
|
||||||
#: src/renderer/components/menu/menu-actions.tsx:49
|
#: src/renderer/components/menu/menu-actions.tsx:49
|
||||||
#: src/renderer/components/menu/menu-actions.tsx:85
|
#: src/renderer/components/menu/menu-actions.tsx:85
|
||||||
@ -2022,7 +2033,7 @@ msgstr "Remove"
|
|||||||
msgid "Remove <0>{releaseNames}</0>?"
|
msgid "Remove <0>{releaseNames}</0>?"
|
||||||
msgstr "Remove <0>{releaseNames}</0>?"
|
msgstr "Remove <0>{releaseNames}</0>?"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:51
|
#: src/renderer/components/+workspaces/workspaces.tsx:52
|
||||||
msgid "Remove Workspace"
|
msgid "Remove Workspace"
|
||||||
msgstr "Remove Workspace"
|
msgstr "Remove Workspace"
|
||||||
|
|
||||||
@ -2050,7 +2061,7 @@ msgstr "Remove selected items ({0})"
|
|||||||
msgid "Remove {resourceKind} <0>{resourceName}</0>?"
|
msgid "Remove {resourceKind} <0>{resourceName}</0>?"
|
||||||
msgstr "Remove {resourceKind} <0>{resourceName}</0>?"
|
msgstr "Remove {resourceKind} <0>{resourceName}</0>?"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:114
|
#: src/renderer/components/+preferences/preferences.tsx:122
|
||||||
msgid "Removing helm branch <0>{0}</0> has failed: {1}"
|
msgid "Removing helm branch <0>{0}</0> has failed: {1}"
|
||||||
msgstr "Removing helm branch <0>{0}</0> has failed: {1}"
|
msgstr "Removing helm branch <0>{0}</0> has failed: {1}"
|
||||||
|
|
||||||
@ -2074,7 +2085,7 @@ msgstr "Replicas"
|
|||||||
msgid "Repo/Name"
|
msgid "Repo/Name"
|
||||||
msgstr "Repo/Name"
|
msgstr "Repo/Name"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:133
|
#: src/renderer/components/+preferences/preferences.tsx:146
|
||||||
msgid "Repositories"
|
msgid "Repositories"
|
||||||
msgstr "Repositories"
|
msgstr "Repositories"
|
||||||
|
|
||||||
@ -2109,7 +2120,7 @@ msgstr "Required Drop Capabilities"
|
|||||||
msgid "Required field"
|
msgid "Required field"
|
||||||
msgstr "Required field"
|
msgstr "Required field"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:250
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:235
|
||||||
#: src/renderer/components/item-object-list/page-filters-list.tsx:31
|
#: src/renderer/components/item-object-list/page-filters-list.tsx:31
|
||||||
msgid "Reset"
|
msgid "Reset"
|
||||||
msgstr "Reset"
|
msgstr "Reset"
|
||||||
@ -2252,7 +2263,7 @@ msgstr "Runtime Class"
|
|||||||
#: src/renderer/components/+config-maps/config-map-details.tsx:78
|
#: src/renderer/components/+config-maps/config-map-details.tsx:78
|
||||||
#: src/renderer/components/+config-secrets/secret-details.tsx:97
|
#: src/renderer/components/+config-secrets/secret-details.tsx:97
|
||||||
#: src/renderer/components/+workloads-pods/pod-logs-dialog.tsx:216
|
#: src/renderer/components/+workloads-pods/pod-logs-dialog.tsx:216
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:120
|
#: src/renderer/components/+workspaces/workspaces.tsx:132
|
||||||
#: src/renderer/components/dock/edit-resource.tsx:88
|
#: src/renderer/components/dock/edit-resource.tsx:88
|
||||||
msgid "Save"
|
msgid "Save"
|
||||||
msgstr "Save"
|
msgstr "Save"
|
||||||
@ -2341,13 +2352,13 @@ msgstr "Select a quota.."
|
|||||||
#~ msgid "Select context(s)"
|
#~ msgid "Select context(s)"
|
||||||
#~ msgstr "Select context(s)"
|
#~ msgstr "Select context(s)"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:272
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:257
|
||||||
#~ msgid "Select contexts"
|
msgid "Select contexts"
|
||||||
#~ msgstr "Select contexts"
|
msgstr "Select contexts"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:272
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:272
|
||||||
msgid "Select contexts (available: {0})"
|
#~ msgid "Select contexts (available: {0})"
|
||||||
msgstr "Select contexts (available: {0})"
|
#~ msgstr "Select contexts (available: {0})"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:76
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:76
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:76
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:76
|
||||||
@ -2371,7 +2382,7 @@ msgstr "Select custom kubeconfig file"
|
|||||||
#~ msgid "Select kubeconfig"
|
#~ msgid "Select kubeconfig"
|
||||||
#~ msgstr "Select kubeconfig"
|
#~ msgstr "Select kubeconfig"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:244
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:229
|
||||||
msgid "Select kubeconfig file"
|
msgid "Select kubeconfig file"
|
||||||
msgstr "Select kubeconfig file"
|
msgstr "Select kubeconfig file"
|
||||||
|
|
||||||
@ -2399,7 +2410,7 @@ msgstr "Select service accounts"
|
|||||||
#~ msgid "Selected contexts ({0}): <0>{1}</0>"
|
#~ msgid "Selected contexts ({0}): <0>{1}</0>"
|
||||||
#~ msgstr "Selected contexts ({0}): <0>{1}</0>"
|
#~ msgstr "Selected contexts ({0}): <0>{1}</0>"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:271
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:256
|
||||||
msgid "Selected contexts: <0>{0}</0>"
|
msgid "Selected contexts: <0>{0}</0>"
|
||||||
msgstr "Selected contexts: <0>{0}</0>"
|
msgstr "Selected contexts: <0>{0}</0>"
|
||||||
|
|
||||||
@ -2503,7 +2514,6 @@ msgid "Stateful Sets"
|
|||||||
msgstr "Stateful Sets"
|
msgstr "Stateful Sets"
|
||||||
|
|
||||||
#: src/renderer/components/+workloads/workloads.tsx:61
|
#: src/renderer/components/+workloads/workloads.tsx:61
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:52
|
|
||||||
msgid "StatefulSets"
|
msgid "StatefulSets"
|
||||||
msgstr "StatefulSets"
|
msgstr "StatefulSets"
|
||||||
|
|
||||||
@ -2605,11 +2615,11 @@ msgstr "TLS"
|
|||||||
msgid "Taints"
|
msgid "Taints"
|
||||||
msgstr "Taints"
|
msgstr "Taints"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:161
|
#: src/renderer/components/+preferences/preferences.tsx:168
|
||||||
msgid "Telemetry & Usage Tracking"
|
msgid "Telemetry & Usage Tracking"
|
||||||
msgstr "Telemetry & Usage Tracking"
|
msgstr "Telemetry & Usage Tracking"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:164
|
#: src/renderer/components/+preferences/preferences.tsx:171
|
||||||
msgid "Telemetry & usage data is collected to continuously improve the Lens experience."
|
msgid "Telemetry & usage data is collected to continuously improve the Lens experience."
|
||||||
msgstr "Telemetry & usage data is collected to continuously improve the Lens experience."
|
msgstr "Telemetry & usage data is collected to continuously improve the Lens experience."
|
||||||
|
|
||||||
@ -2629,15 +2639,19 @@ msgstr "There are no logs available for container."
|
|||||||
msgid "There are no logs available."
|
msgid "There are no logs available."
|
||||||
msgstr "There are no logs available."
|
msgstr "There are no logs available."
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:5
|
#: src/renderer/components/input/input.validators.ts:6
|
||||||
msgid "This field is required"
|
msgid "This field is required"
|
||||||
msgstr "This field is required"
|
msgstr "This field is required"
|
||||||
|
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:106
|
#: src/renderer/components/input/input.validators.ts:31
|
||||||
|
msgid "This field must be a valid path"
|
||||||
|
msgstr "This field must be a valid path"
|
||||||
|
|
||||||
|
#: src/renderer/components/+landing-page/landing-page.tsx:25
|
||||||
msgid "This is the quick launch menu."
|
msgid "This is the quick launch menu."
|
||||||
msgstr "This is the quick launch menu."
|
msgstr "This is the quick launch menu."
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:156
|
#: src/renderer/components/+preferences/preferences.tsx:163
|
||||||
msgid "This will make Lens to trust ANY certificate authority without any validations."
|
msgid "This will make Lens to trust ANY certificate authority without any validations."
|
||||||
msgstr "This will make Lens to trust ANY certificate authority without any validations."
|
msgstr "This will make Lens to trust ANY certificate authority without any validations."
|
||||||
|
|
||||||
@ -2661,13 +2675,13 @@ msgstr "Tolerations"
|
|||||||
msgid "Transmit"
|
msgid "Transmit"
|
||||||
msgstr "Transmit"
|
msgstr "Transmit"
|
||||||
|
|
||||||
#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:107
|
#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:106
|
||||||
#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:79
|
#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:79
|
||||||
#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:80
|
#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:80
|
||||||
msgid "Trigger"
|
msgid "Trigger"
|
||||||
msgstr "Trigger"
|
msgstr "Trigger"
|
||||||
|
|
||||||
#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:103
|
#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:102
|
||||||
msgid "Trigger CronJob <0>{cronjobName}</0>"
|
msgid "Trigger CronJob <0>{cronjobName}</0>"
|
||||||
msgstr "Trigger CronJob <0>{cronjobName}</0>"
|
msgstr "Trigger CronJob <0>{cronjobName}</0>"
|
||||||
|
|
||||||
@ -2690,7 +2704,7 @@ msgstr "Trigger CronJob <0>{cronjobName}</0>"
|
|||||||
msgid "Type"
|
msgid "Type"
|
||||||
msgstr "Type"
|
msgstr "Type"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:148
|
#: src/renderer/components/+preferences/preferences.tsx:138
|
||||||
msgid "Type HTTP proxy url (example: http://proxy.acme.org:8080)"
|
msgid "Type HTTP proxy url (example: http://proxy.acme.org:8080)"
|
||||||
msgstr "Type HTTP proxy url (example: http://proxy.acme.org:8080)"
|
msgstr "Type HTTP proxy url (example: http://proxy.acme.org:8080)"
|
||||||
|
|
||||||
@ -2827,11 +2841,11 @@ msgstr "Waiting services to be running"
|
|||||||
msgid "Warnings: {0}"
|
msgid "Warnings: {0}"
|
||||||
msgstr "Warnings: {0}"
|
msgstr "Warnings: {0}"
|
||||||
|
|
||||||
#: src/renderer/components/+landing-page/landing-page.tsx:20
|
#: src/renderer/components/+landing-page/landing-page.tsx:34
|
||||||
msgid "Welcome!"
|
msgid "Welcome!"
|
||||||
msgstr "Welcome!"
|
msgstr "Welcome!"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:79
|
#: src/renderer/components/+workspaces/workspaces.tsx:88
|
||||||
msgid "What is a Workspace?"
|
msgid "What is a Workspace?"
|
||||||
msgstr "What is a Workspace?"
|
msgstr "What is a Workspace?"
|
||||||
|
|
||||||
@ -2844,19 +2858,19 @@ msgid "Workloads"
|
|||||||
msgstr "Workloads"
|
msgstr "Workloads"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspace-menu.tsx:39
|
#: src/renderer/components/+workspaces/workspace-menu.tsx:39
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:91
|
#: src/renderer/components/+workspaces/workspaces.tsx:100
|
||||||
msgid "Workspaces"
|
msgid "Workspaces"
|
||||||
msgstr "Workspaces"
|
msgstr "Workspaces"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:81
|
#: src/renderer/components/+workspaces/workspaces.tsx:90
|
||||||
msgid "Workspaces are used to organize number of clusters into logical groups."
|
msgid "Workspaces are used to organize number of clusters into logical groups."
|
||||||
msgstr "Workspaces are used to organize number of clusters into logical groups."
|
msgstr "Workspaces are used to organize number of clusters into logical groups."
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:10
|
#: src/renderer/components/input/input.validators.ts:11
|
||||||
msgid "Wrong email format"
|
msgid "Wrong email format"
|
||||||
msgstr "Wrong email format"
|
msgstr "Wrong email format"
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:25
|
#: src/renderer/components/input/input.validators.ts:26
|
||||||
msgid "Wrong url format"
|
msgid "Wrong url format"
|
||||||
msgstr "Wrong url format"
|
msgstr "Wrong url format"
|
||||||
|
|
||||||
@ -2915,7 +2929,7 @@ msgstr "listKind"
|
|||||||
msgid "never"
|
msgid "never"
|
||||||
msgstr "never"
|
msgstr "never"
|
||||||
|
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:121
|
#: src/renderer/components/cluster-manager/clusters-menu.tsx:133
|
||||||
msgid "new"
|
msgid "new"
|
||||||
msgstr "new"
|
msgstr "new"
|
||||||
|
|
||||||
|
|||||||
@ -25,7 +25,7 @@ msgstr ""
|
|||||||
msgid "(as a percentage of request)"
|
msgid "(as a percentage of request)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:108
|
#: src/renderer/components/+workspaces/workspaces.tsx:121
|
||||||
msgid "(current)"
|
msgid "(current)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -57,11 +57,11 @@ msgstr ""
|
|||||||
#~ msgid "A HTTP proxy server URL (format: http://<address>:<port>)"
|
#~ msgid "A HTTP proxy server URL (format: http://<address>:<port>)"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:40
|
#: src/renderer/components/input/input.validators.ts:46
|
||||||
msgid "A System Name must be lowercase DNS labels separated by dots. DNS labels are alphanumerics and dashes enclosed by alphanumerics."
|
msgid "A System Name must be lowercase DNS labels separated by dots. DNS labels are alphanumerics and dashes enclosed by alphanumerics."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:84
|
#: src/renderer/components/+workspaces/workspaces.tsx:93
|
||||||
msgid "A single workspaces contains a list of clusters and their full configuration."
|
msgid "A single workspaces contains a list of clusters and their full configuration."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -87,8 +87,8 @@ msgstr ""
|
|||||||
msgid "Active"
|
msgid "Active"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:303
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:288
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:118
|
#: src/renderer/components/cluster-manager/clusters-menu.tsx:130
|
||||||
msgid "Add Cluster"
|
msgid "Add Cluster"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ msgstr ""
|
|||||||
msgid "Add RoleBinding"
|
msgid "Add RoleBinding"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:125
|
#: src/renderer/components/+workspaces/workspaces.tsx:138
|
||||||
msgid "Add Workspace"
|
msgid "Add Workspace"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ msgstr ""
|
|||||||
#~ msgid "Add cluster"
|
#~ msgid "Add cluster"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:320
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:305
|
||||||
msgid "Add cluster(s)"
|
msgid "Add cluster(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ msgstr ""
|
|||||||
#~ msgid "Adding clusters: <0>{0}</0>"
|
#~ msgid "Adding clusters: <0>{0}</0>"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:103
|
#: src/renderer/components/+preferences/preferences.tsx:111
|
||||||
msgid "Adding helm branch <0>{0}</0> has failed: {1}"
|
msgid "Adding helm branch <0>{0}</0> has failed: {1}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ msgstr ""
|
|||||||
msgid "Age"
|
msgid "Age"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:64
|
#: src/renderer/components/+workspaces/workspaces.tsx:65
|
||||||
msgid "All clusters within workspace will be cleared as well"
|
msgid "All clusters within workspace will be cleared as well"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -219,11 +219,11 @@ msgstr ""
|
|||||||
msgid "Allow Privilege Escalation"
|
msgid "Allow Privilege Escalation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:162
|
#: src/renderer/components/+preferences/preferences.tsx:169
|
||||||
msgid "Allow telemetry & usage tracking"
|
msgid "Allow telemetry & usage tracking"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:154
|
#: src/renderer/components/+preferences/preferences.tsx:161
|
||||||
msgid "Allow untrusted Certificate Authorities"
|
msgid "Allow untrusted Certificate Authorities"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ msgstr ""
|
|||||||
msgid "Apps"
|
msgid "Apps"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:61
|
#: src/renderer/components/+workspaces/workspaces.tsx:62
|
||||||
msgid "Are you sure you want remove workspace <0>{0}</0>?"
|
msgid "Are you sure you want remove workspace <0>{0}</0>?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -293,7 +293,7 @@ msgstr ""
|
|||||||
msgid "Arguments"
|
msgid "Arguments"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:108
|
#: src/renderer/components/+landing-page/landing-page.tsx:27
|
||||||
msgid "Associate clusters and choose the ones you want to access via quick launch menu by clicking the + button."
|
msgid "Associate clusters and choose the ones you want to access via quick launch menu by clicking the + button."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -323,7 +323,7 @@ msgstr ""
|
|||||||
msgid "Bindings"
|
msgid "Bindings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:251
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:236
|
||||||
msgid "Browse"
|
msgid "Browse"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -402,7 +402,7 @@ msgstr ""
|
|||||||
msgid "CPU:"
|
msgid "CPU:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:119
|
#: src/renderer/components/+workspaces/workspaces.tsx:133
|
||||||
#: src/renderer/components/confirm-dialog/confirm-dialog.tsx:44
|
#: src/renderer/components/confirm-dialog/confirm-dialog.tsx:44
|
||||||
#: src/renderer/components/dock/info-panel.tsx:97
|
#: src/renderer/components/dock/info-panel.tsx:97
|
||||||
#: src/renderer/components/wizard/wizard.tsx:130
|
#: src/renderer/components/wizard/wizard.tsx:130
|
||||||
@ -422,7 +422,7 @@ msgstr ""
|
|||||||
msgid "Capacity"
|
msgid "Capacity"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:153
|
#: src/renderer/components/+preferences/preferences.tsx:160
|
||||||
msgid "Certificate Trust"
|
msgid "Certificate Trust"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -497,7 +497,7 @@ msgstr ""
|
|||||||
msgid "Cluster Issuers"
|
msgid "Cluster Issuers"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:126
|
#: src/renderer/components/+preferences/preferences.tsx:134
|
||||||
msgid "Color Theme"
|
msgid "Color Theme"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -708,7 +708,6 @@ msgid "Cron Jobs"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workloads/workloads.tsx:77
|
#: src/renderer/components/+workloads/workloads.tsx:77
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:67
|
|
||||||
msgid "CronJobs"
|
msgid "CronJobs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -755,7 +754,6 @@ msgid "Daemon Sets"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workloads/workloads.tsx:53
|
#: src/renderer/components/+workloads/workloads.tsx:53
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:57
|
|
||||||
msgid "DaemonSets"
|
msgid "DaemonSets"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -780,11 +778,15 @@ msgstr ""
|
|||||||
msgid "Default Runtime Class Name"
|
msgid "Default Runtime Class Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/renderer/components/+preferences/kubectl-binaries.tsx:30
|
||||||
|
msgid "Default:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+custom-resources/custom-resources.tsx:22
|
#: src/renderer/components/+custom-resources/custom-resources.tsx:22
|
||||||
msgid "Definitions"
|
msgid "Definitions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:113
|
#: src/renderer/components/+workspaces/workspaces.tsx:126
|
||||||
#: src/renderer/components/menu/menu-actions.tsx:84
|
#: src/renderer/components/menu/menu-actions.tsx:84
|
||||||
msgid "Delete"
|
msgid "Delete"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -795,12 +797,11 @@ msgstr ""
|
|||||||
|
|
||||||
#: src/renderer/components/+workloads/workloads.tsx:45
|
#: src/renderer/components/+workloads/workloads.tsx:45
|
||||||
#: src/renderer/components/+workloads-deployments/deployments.tsx:57
|
#: src/renderer/components/+workloads-deployments/deployments.tsx:57
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:47
|
|
||||||
msgid "Deployments"
|
msgid "Deployments"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+apps-helm-charts/helm-charts.tsx:65
|
#: src/renderer/components/+apps-helm-charts/helm-charts.tsx:65
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:118
|
#: src/renderer/components/+workspaces/workspaces.tsx:131
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -813,7 +814,7 @@ msgstr ""
|
|||||||
msgid "Desired number of replicas"
|
msgid "Desired number of replicas"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:64
|
#: src/renderer/components/cluster-manager/clusters-menu.tsx:65
|
||||||
msgid "Disconnect"
|
msgid "Disconnect"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -827,7 +828,7 @@ msgstr ""
|
|||||||
msgid "Disk:"
|
msgid "Disk:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:158
|
#: src/renderer/components/+preferences/preferences.tsx:165
|
||||||
msgid "Does not affect cluster communications!"
|
msgid "Does not affect cluster communications!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -836,14 +837,22 @@ msgid "Domains"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:129
|
#: src/renderer/components/+preferences/preferences.tsx:129
|
||||||
msgid "Download Mirror"
|
#~ msgid "Download Mirror"
|
||||||
msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/kubeconfig-dialog/kubeconfig-dialog.tsx:90
|
#: src/renderer/components/kubeconfig-dialog/kubeconfig-dialog.tsx:90
|
||||||
msgid "Download file"
|
msgid "Download file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:130
|
#: src/renderer/components/+preferences/kubectl-binaries.tsx:39
|
||||||
|
msgid "Download kubectl binaries"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/renderer/components/+preferences/kubectl-binaries.tsx:37
|
||||||
|
msgid "Download kubectl binaries matching to Kubernetes cluster verison."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/renderer/components/+preferences/kubectl-binaries.tsx:41
|
||||||
msgid "Download mirror for kubectl"
|
msgid "Download mirror for kubectl"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -869,7 +878,7 @@ msgstr ""
|
|||||||
msgid "E-mail"
|
msgid "E-mail"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:112
|
#: src/renderer/components/+workspaces/workspaces.tsx:125
|
||||||
#: src/renderer/components/menu/menu-actions.tsx:80
|
#: src/renderer/components/menu/menu-actions.tsx:80
|
||||||
#: src/renderer/components/menu/menu-actions.tsx:81
|
#: src/renderer/components/menu/menu-actions.tsx:81
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@ -991,7 +1000,7 @@ msgstr ""
|
|||||||
msgid "Fs Group"
|
msgid "Fs Group"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+landing-page/landing-page.tsx:23
|
#: src/renderer/components/+landing-page/landing-page.tsx:37
|
||||||
msgid "Get started by associating one or more clusters to Lens."
|
msgid "Get started by associating one or more clusters to Lens."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1013,7 +1022,7 @@ msgstr ""
|
|||||||
msgid "HPA"
|
msgid "HPA"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:147
|
#: src/renderer/components/+preferences/preferences.tsx:137
|
||||||
msgid "HTTP Proxy"
|
msgid "HTTP Proxy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1021,7 +1030,7 @@ msgstr ""
|
|||||||
#~ msgid "HTTP Proxy server. Used for communicating with Kubernetes API."
|
#~ msgid "HTTP Proxy server. Used for communicating with Kubernetes API."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:132
|
#: src/renderer/components/+preferences/preferences.tsx:145
|
||||||
msgid "Helm"
|
msgid "Helm"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1041,7 +1050,7 @@ msgstr ""
|
|||||||
msgid "Helm Upgrade: {0}"
|
msgid "Helm Upgrade: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:47
|
#: src/renderer/components/+preferences/preferences.tsx:51
|
||||||
msgid "Helm branch <0>{0}</0> already in use"
|
msgid "Helm branch <0>{0}</0> already in use"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1148,11 +1157,11 @@ msgstr ""
|
|||||||
msgid "Installing..."
|
msgid "Installing..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:44
|
#: src/renderer/components/input/input.validators.ts:50
|
||||||
msgid "Invalid account ID"
|
msgid "Invalid account ID"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:15
|
#: src/renderer/components/input/input.validators.ts:16
|
||||||
msgid "Invalid number"
|
msgid "Invalid number"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1188,7 +1197,6 @@ msgstr ""
|
|||||||
#: src/renderer/components/+workloads/workloads.tsx:69
|
#: src/renderer/components/+workloads/workloads.tsx:69
|
||||||
#: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:62
|
#: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:62
|
||||||
#: src/renderer/components/+workloads-jobs/jobs.tsx:36
|
#: src/renderer/components/+workloads-jobs/jobs.tsx:36
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:62
|
|
||||||
msgid "Jobs"
|
msgid "Jobs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1232,6 +1240,10 @@ msgstr ""
|
|||||||
msgid "Kubeconfig File"
|
msgid "Kubeconfig File"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/renderer/components/+preferences/kubectl-binaries.tsx:35
|
||||||
|
msgid "Kubectl Binary"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+nodes/node-details.tsx:98
|
#: src/renderer/components/+nodes/node-details.tsx:98
|
||||||
msgid "Kubelet version"
|
msgid "Kubelet version"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1348,7 +1360,7 @@ msgstr ""
|
|||||||
msgid "Max Unavailable"
|
msgid "Max Unavailable"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:35
|
#: src/renderer/components/input/input.validators.ts:41
|
||||||
msgid "Maximum length is {maxLength}"
|
msgid "Maximum length is {maxLength}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1424,7 +1436,7 @@ msgstr ""
|
|||||||
msgid "Minimize"
|
msgid "Minimize"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:30
|
#: src/renderer/components/input/input.validators.ts:36
|
||||||
msgid "Minimum length is {minLength}"
|
msgid "Minimum length is {minLength}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1488,7 +1500,7 @@ msgstr ""
|
|||||||
#: src/renderer/components/+workloads-pods/pods.tsx:74
|
#: src/renderer/components/+workloads-pods/pods.tsx:74
|
||||||
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:50
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:50
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulsets.tsx:40
|
#: src/renderer/components/+workloads-statefulsets/statefulsets.tsx:40
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:117
|
#: src/renderer/components/+workspaces/workspaces.tsx:130
|
||||||
#: src/renderer/components/dock/edit-resource.tsx:90
|
#: src/renderer/components/dock/edit-resource.tsx:90
|
||||||
#: src/renderer/components/kube-object/kube-object-meta.tsx:20
|
#: src/renderer/components/kube-object/kube-object-meta.tsx:20
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
@ -1556,7 +1568,7 @@ msgstr ""
|
|||||||
msgid "Namespaces: {0}"
|
msgid "Namespaces: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:157
|
#: src/renderer/components/+preferences/preferences.tsx:164
|
||||||
msgid "Needed with some corporate proxies that do certificate re-writing."
|
msgid "Needed with some corporate proxies that do certificate re-writing."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1609,7 +1621,7 @@ msgstr ""
|
|||||||
#~ msgid "No contexts available or they already added"
|
#~ msgid "No contexts available or they already added"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:275
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:260
|
||||||
msgid "No contexts available or they have been added already"
|
msgid "No contexts available or they have been added already"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1725,7 +1737,7 @@ msgid "Organization"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workloads/workloads.tsx:29
|
#: src/renderer/components/+workloads/workloads.tsx:29
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:35
|
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:45
|
||||||
msgid "Overview"
|
msgid "Overview"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1741,7 +1753,7 @@ msgstr ""
|
|||||||
msgid "Parameters"
|
msgid "Parameters"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:245
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:230
|
||||||
msgid "Paste as text"
|
msgid "Paste as text"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1831,7 +1843,6 @@ msgstr ""
|
|||||||
#: src/renderer/components/+workloads/workloads.tsx:37
|
#: src/renderer/components/+workloads/workloads.tsx:37
|
||||||
#: src/renderer/components/+workloads-daemonsets/daemonsets.tsx:47
|
#: src/renderer/components/+workloads-daemonsets/daemonsets.tsx:47
|
||||||
#: src/renderer/components/+workloads-deployments/deployments.tsx:60
|
#: src/renderer/components/+workloads-deployments/deployments.tsx:60
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:42
|
|
||||||
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:89
|
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:89
|
||||||
#: src/renderer/components/+workloads-pods/pods.tsx:73
|
#: src/renderer/components/+workloads-pods/pods.tsx:73
|
||||||
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:52
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:52
|
||||||
@ -1882,7 +1893,7 @@ msgstr ""
|
|||||||
#~ msgid "Pro-Tip: paste kubeconfig to collect available contexts"
|
#~ msgid "Pro-Tip: paste kubeconfig to collect available contexts"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:263
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:248
|
||||||
msgid "Pro-Tip: paste kubeconfig to get available contexts"
|
msgid "Pro-Tip: paste kubeconfig to get available contexts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1890,7 +1901,7 @@ msgstr ""
|
|||||||
#~ msgid "Pro-Tip: paste kubeconfig to parse available contexts"
|
#~ msgid "Pro-Tip: paste kubeconfig to parse available contexts"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:254
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:239
|
||||||
msgid "Pro-Tip: you can also drag-n-drop kubeconfig file to this area"
|
msgid "Pro-Tip: you can also drag-n-drop kubeconfig file to this area"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1907,11 +1918,11 @@ msgstr ""
|
|||||||
msgid "Provisioner"
|
msgid "Provisioner"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:150
|
#: src/renderer/components/+preferences/preferences.tsx:140
|
||||||
msgid "Proxy is used only for non-cluster communication."
|
msgid "Proxy is used only for non-cluster communication."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:308
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:293
|
||||||
msgid "Proxy settings"
|
msgid "Proxy settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1991,10 +2002,10 @@ msgstr ""
|
|||||||
msgid "Releases"
|
msgid "Releases"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:139
|
#: src/renderer/components/+preferences/preferences.tsx:152
|
||||||
#: src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx:60
|
#: src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx:60
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:74
|
#: src/renderer/components/cluster-manager/clusters-menu.tsx:76
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:80
|
#: src/renderer/components/cluster-manager/clusters-menu.tsx:82
|
||||||
#: src/renderer/components/item-object-list/item-list-layout.tsx:179
|
#: src/renderer/components/item-object-list/item-list-layout.tsx:179
|
||||||
#: src/renderer/components/menu/menu-actions.tsx:49
|
#: src/renderer/components/menu/menu-actions.tsx:49
|
||||||
#: src/renderer/components/menu/menu-actions.tsx:85
|
#: src/renderer/components/menu/menu-actions.tsx:85
|
||||||
@ -2005,7 +2016,7 @@ msgstr ""
|
|||||||
msgid "Remove <0>{releaseNames}</0>?"
|
msgid "Remove <0>{releaseNames}</0>?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:51
|
#: src/renderer/components/+workspaces/workspaces.tsx:52
|
||||||
msgid "Remove Workspace"
|
msgid "Remove Workspace"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2033,7 +2044,7 @@ msgstr ""
|
|||||||
msgid "Remove {resourceKind} <0>{resourceName}</0>?"
|
msgid "Remove {resourceKind} <0>{resourceName}</0>?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:114
|
#: src/renderer/components/+preferences/preferences.tsx:122
|
||||||
msgid "Removing helm branch <0>{0}</0> has failed: {1}"
|
msgid "Removing helm branch <0>{0}</0> has failed: {1}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2057,7 +2068,7 @@ msgstr ""
|
|||||||
msgid "Repo/Name"
|
msgid "Repo/Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:133
|
#: src/renderer/components/+preferences/preferences.tsx:146
|
||||||
msgid "Repositories"
|
msgid "Repositories"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2092,7 +2103,7 @@ msgstr ""
|
|||||||
msgid "Required field"
|
msgid "Required field"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:250
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:235
|
||||||
#: src/renderer/components/item-object-list/page-filters-list.tsx:31
|
#: src/renderer/components/item-object-list/page-filters-list.tsx:31
|
||||||
msgid "Reset"
|
msgid "Reset"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2235,7 +2246,7 @@ msgstr ""
|
|||||||
#: src/renderer/components/+config-maps/config-map-details.tsx:78
|
#: src/renderer/components/+config-maps/config-map-details.tsx:78
|
||||||
#: src/renderer/components/+config-secrets/secret-details.tsx:97
|
#: src/renderer/components/+config-secrets/secret-details.tsx:97
|
||||||
#: src/renderer/components/+workloads-pods/pod-logs-dialog.tsx:216
|
#: src/renderer/components/+workloads-pods/pod-logs-dialog.tsx:216
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:120
|
#: src/renderer/components/+workspaces/workspaces.tsx:132
|
||||||
#: src/renderer/components/dock/edit-resource.tsx:88
|
#: src/renderer/components/dock/edit-resource.tsx:88
|
||||||
msgid "Save"
|
msgid "Save"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2324,13 +2335,13 @@ msgstr ""
|
|||||||
#~ msgid "Select context(s)"
|
#~ msgid "Select context(s)"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:272
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:257
|
||||||
#~ msgid "Select contexts"
|
msgid "Select contexts"
|
||||||
#~ msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:272
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:272
|
||||||
msgid "Select contexts (available: {0})"
|
#~ msgid "Select contexts (available: {0})"
|
||||||
msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:76
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:76
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:76
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:76
|
||||||
@ -2354,7 +2365,7 @@ msgstr ""
|
|||||||
#~ msgid "Select kubeconfig"
|
#~ msgid "Select kubeconfig"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:244
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:229
|
||||||
msgid "Select kubeconfig file"
|
msgid "Select kubeconfig file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2382,7 +2393,7 @@ msgstr ""
|
|||||||
#~ msgid "Selected contexts ({0}): <0>{1}</0>"
|
#~ msgid "Selected contexts ({0}): <0>{1}</0>"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:271
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:256
|
||||||
msgid "Selected contexts: <0>{0}</0>"
|
msgid "Selected contexts: <0>{0}</0>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2486,7 +2497,6 @@ msgid "Stateful Sets"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workloads/workloads.tsx:61
|
#: src/renderer/components/+workloads/workloads.tsx:61
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:52
|
|
||||||
msgid "StatefulSets"
|
msgid "StatefulSets"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2588,11 +2598,11 @@ msgstr ""
|
|||||||
msgid "Taints"
|
msgid "Taints"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:161
|
#: src/renderer/components/+preferences/preferences.tsx:168
|
||||||
msgid "Telemetry & Usage Tracking"
|
msgid "Telemetry & Usage Tracking"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:164
|
#: src/renderer/components/+preferences/preferences.tsx:171
|
||||||
msgid "Telemetry & usage data is collected to continuously improve the Lens experience."
|
msgid "Telemetry & usage data is collected to continuously improve the Lens experience."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2612,15 +2622,19 @@ msgstr ""
|
|||||||
msgid "There are no logs available."
|
msgid "There are no logs available."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:5
|
#: src/renderer/components/input/input.validators.ts:6
|
||||||
msgid "This field is required"
|
msgid "This field is required"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:106
|
#: src/renderer/components/input/input.validators.ts:31
|
||||||
|
msgid "This field must be a valid path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/renderer/components/+landing-page/landing-page.tsx:25
|
||||||
msgid "This is the quick launch menu."
|
msgid "This is the quick launch menu."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:156
|
#: src/renderer/components/+preferences/preferences.tsx:163
|
||||||
msgid "This will make Lens to trust ANY certificate authority without any validations."
|
msgid "This will make Lens to trust ANY certificate authority without any validations."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2644,13 +2658,13 @@ msgstr ""
|
|||||||
msgid "Transmit"
|
msgid "Transmit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:107
|
#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:106
|
||||||
#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:79
|
#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:79
|
||||||
#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:80
|
#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:80
|
||||||
msgid "Trigger"
|
msgid "Trigger"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:103
|
#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:102
|
||||||
msgid "Trigger CronJob <0>{cronjobName}</0>"
|
msgid "Trigger CronJob <0>{cronjobName}</0>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2673,7 +2687,7 @@ msgstr ""
|
|||||||
msgid "Type"
|
msgid "Type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:148
|
#: src/renderer/components/+preferences/preferences.tsx:138
|
||||||
msgid "Type HTTP proxy url (example: http://proxy.acme.org:8080)"
|
msgid "Type HTTP proxy url (example: http://proxy.acme.org:8080)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2810,11 +2824,11 @@ msgstr ""
|
|||||||
msgid "Warnings: {0}"
|
msgid "Warnings: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+landing-page/landing-page.tsx:20
|
#: src/renderer/components/+landing-page/landing-page.tsx:34
|
||||||
msgid "Welcome!"
|
msgid "Welcome!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:79
|
#: src/renderer/components/+workspaces/workspaces.tsx:88
|
||||||
msgid "What is a Workspace?"
|
msgid "What is a Workspace?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2827,19 +2841,19 @@ msgid "Workloads"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspace-menu.tsx:39
|
#: src/renderer/components/+workspaces/workspace-menu.tsx:39
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:91
|
#: src/renderer/components/+workspaces/workspaces.tsx:100
|
||||||
msgid "Workspaces"
|
msgid "Workspaces"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:81
|
#: src/renderer/components/+workspaces/workspaces.tsx:90
|
||||||
msgid "Workspaces are used to organize number of clusters into logical groups."
|
msgid "Workspaces are used to organize number of clusters into logical groups."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:10
|
#: src/renderer/components/input/input.validators.ts:11
|
||||||
msgid "Wrong email format"
|
msgid "Wrong email format"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:25
|
#: src/renderer/components/input/input.validators.ts:26
|
||||||
msgid "Wrong url format"
|
msgid "Wrong url format"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2898,7 +2912,7 @@ msgstr ""
|
|||||||
msgid "never"
|
msgid "never"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:121
|
#: src/renderer/components/cluster-manager/clusters-menu.tsx:133
|
||||||
msgid "new"
|
msgid "new"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,7 @@ msgstr ""
|
|||||||
msgid "(as a percentage of request)"
|
msgid "(as a percentage of request)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:108
|
#: src/renderer/components/+workspaces/workspaces.tsx:121
|
||||||
msgid "(current)"
|
msgid "(current)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -58,11 +58,11 @@ msgstr ""
|
|||||||
#~ msgid "A HTTP proxy server URL (format: http://<address>:<port>)"
|
#~ msgid "A HTTP proxy server URL (format: http://<address>:<port>)"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:40
|
#: src/renderer/components/input/input.validators.ts:46
|
||||||
msgid "A System Name must be lowercase DNS labels separated by dots. DNS labels are alphanumerics and dashes enclosed by alphanumerics."
|
msgid "A System Name must be lowercase DNS labels separated by dots. DNS labels are alphanumerics and dashes enclosed by alphanumerics."
|
||||||
msgstr "Это поле может содержать только латинские буквы в нижнем регистре, номера и дефис."
|
msgstr "Это поле может содержать только латинские буквы в нижнем регистре, номера и дефис."
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:84
|
#: src/renderer/components/+workspaces/workspaces.tsx:93
|
||||||
msgid "A single workspaces contains a list of clusters and their full configuration."
|
msgid "A single workspaces contains a list of clusters and their full configuration."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -88,8 +88,8 @@ msgstr "Название аккаунта"
|
|||||||
msgid "Active"
|
msgid "Active"
|
||||||
msgstr "Активный"
|
msgstr "Активный"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:303
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:288
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:118
|
#: src/renderer/components/cluster-manager/clusters-menu.tsx:130
|
||||||
msgid "Add Cluster"
|
msgid "Add Cluster"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ msgstr "Добавить Namespace"
|
|||||||
msgid "Add RoleBinding"
|
msgid "Add RoleBinding"
|
||||||
msgstr "Добавить привязку ролей"
|
msgstr "Добавить привязку ролей"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:125
|
#: src/renderer/components/+workspaces/workspaces.tsx:138
|
||||||
msgid "Add Workspace"
|
msgid "Add Workspace"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ msgstr "Добавить привязки к {name}"
|
|||||||
#~ msgid "Add cluster"
|
#~ msgid "Add cluster"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:320
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:305
|
||||||
msgid "Add cluster(s)"
|
msgid "Add cluster(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ msgstr "Добавить поле"
|
|||||||
#~ msgid "Adding clusters: <0>{0}</0>"
|
#~ msgid "Adding clusters: <0>{0}</0>"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:103
|
#: src/renderer/components/+preferences/preferences.tsx:111
|
||||||
msgid "Adding helm branch <0>{0}</0> has failed: {1}"
|
msgid "Adding helm branch <0>{0}</0> has failed: {1}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ msgstr "Аффинитеты"
|
|||||||
msgid "Age"
|
msgid "Age"
|
||||||
msgstr "Возраст"
|
msgstr "Возраст"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:64
|
#: src/renderer/components/+workspaces/workspaces.tsx:65
|
||||||
msgid "All clusters within workspace will be cleared as well"
|
msgid "All clusters within workspace will be cleared as well"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -220,11 +220,11 @@ msgstr ""
|
|||||||
msgid "Allow Privilege Escalation"
|
msgid "Allow Privilege Escalation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:162
|
#: src/renderer/components/+preferences/preferences.tsx:169
|
||||||
msgid "Allow telemetry & usage tracking"
|
msgid "Allow telemetry & usage tracking"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:154
|
#: src/renderer/components/+preferences/preferences.tsx:161
|
||||||
msgid "Allow untrusted Certificate Authorities"
|
msgid "Allow untrusted Certificate Authorities"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -282,7 +282,7 @@ msgstr "Применение.."
|
|||||||
msgid "Apps"
|
msgid "Apps"
|
||||||
msgstr "Приложения"
|
msgstr "Приложения"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:61
|
#: src/renderer/components/+workspaces/workspaces.tsx:62
|
||||||
msgid "Are you sure you want remove workspace <0>{0}</0>?"
|
msgid "Are you sure you want remove workspace <0>{0}</0>?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -294,7 +294,7 @@ msgstr "Выполнить команду drain для ноды <0>{nodeName}</0
|
|||||||
msgid "Arguments"
|
msgid "Arguments"
|
||||||
msgstr "Аргументы"
|
msgstr "Аргументы"
|
||||||
|
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:108
|
#: src/renderer/components/+landing-page/landing-page.tsx:27
|
||||||
msgid "Associate clusters and choose the ones you want to access via quick launch menu by clicking the + button."
|
msgid "Associate clusters and choose the ones you want to access via quick launch menu by clicking the + button."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -324,7 +324,7 @@ msgstr "Цели привязки"
|
|||||||
msgid "Bindings"
|
msgid "Bindings"
|
||||||
msgstr "Привязки"
|
msgstr "Привязки"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:251
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:236
|
||||||
msgid "Browse"
|
msgid "Browse"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -403,7 +403,7 @@ msgstr "Запросы к процессору"
|
|||||||
msgid "CPU:"
|
msgid "CPU:"
|
||||||
msgstr "CPU:"
|
msgstr "CPU:"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:119
|
#: src/renderer/components/+workspaces/workspaces.tsx:133
|
||||||
#: src/renderer/components/confirm-dialog/confirm-dialog.tsx:44
|
#: src/renderer/components/confirm-dialog/confirm-dialog.tsx:44
|
||||||
#: src/renderer/components/dock/info-panel.tsx:97
|
#: src/renderer/components/dock/info-panel.tsx:97
|
||||||
#: src/renderer/components/wizard/wizard.tsx:130
|
#: src/renderer/components/wizard/wizard.tsx:130
|
||||||
@ -423,7 +423,7 @@ msgstr "Отмена"
|
|||||||
msgid "Capacity"
|
msgid "Capacity"
|
||||||
msgstr "Емкость"
|
msgstr "Емкость"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:153
|
#: src/renderer/components/+preferences/preferences.tsx:160
|
||||||
msgid "Certificate Trust"
|
msgid "Certificate Trust"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -502,7 +502,7 @@ msgstr "IP-адрес кластера"
|
|||||||
msgid "Cluster Issuers"
|
msgid "Cluster Issuers"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:126
|
#: src/renderer/components/+preferences/preferences.tsx:134
|
||||||
msgid "Color Theme"
|
msgid "Color Theme"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -713,7 +713,6 @@ msgid "Cron Jobs"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workloads/workloads.tsx:77
|
#: src/renderer/components/+workloads/workloads.tsx:77
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:67
|
|
||||||
msgid "CronJobs"
|
msgid "CronJobs"
|
||||||
msgstr "CronJobs"
|
msgstr "CronJobs"
|
||||||
|
|
||||||
@ -760,7 +759,6 @@ msgid "Daemon Sets"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workloads/workloads.tsx:53
|
#: src/renderer/components/+workloads/workloads.tsx:53
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:57
|
|
||||||
msgid "DaemonSets"
|
msgid "DaemonSets"
|
||||||
msgstr "DaemonSets"
|
msgstr "DaemonSets"
|
||||||
|
|
||||||
@ -785,11 +783,15 @@ msgstr ""
|
|||||||
msgid "Default Runtime Class Name"
|
msgid "Default Runtime Class Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/renderer/components/+preferences/kubectl-binaries.tsx:30
|
||||||
|
msgid "Default:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+custom-resources/custom-resources.tsx:22
|
#: src/renderer/components/+custom-resources/custom-resources.tsx:22
|
||||||
msgid "Definitions"
|
msgid "Definitions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:113
|
#: src/renderer/components/+workspaces/workspaces.tsx:126
|
||||||
#: src/renderer/components/menu/menu-actions.tsx:84
|
#: src/renderer/components/menu/menu-actions.tsx:84
|
||||||
msgid "Delete"
|
msgid "Delete"
|
||||||
msgstr "Удалить"
|
msgstr "Удалить"
|
||||||
@ -800,12 +802,11 @@ msgstr ""
|
|||||||
|
|
||||||
#: src/renderer/components/+workloads/workloads.tsx:45
|
#: src/renderer/components/+workloads/workloads.tsx:45
|
||||||
#: src/renderer/components/+workloads-deployments/deployments.tsx:57
|
#: src/renderer/components/+workloads-deployments/deployments.tsx:57
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:47
|
|
||||||
msgid "Deployments"
|
msgid "Deployments"
|
||||||
msgstr "Deployments"
|
msgstr "Deployments"
|
||||||
|
|
||||||
#: src/renderer/components/+apps-helm-charts/helm-charts.tsx:65
|
#: src/renderer/components/+apps-helm-charts/helm-charts.tsx:65
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:118
|
#: src/renderer/components/+workspaces/workspaces.tsx:131
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Описание"
|
msgstr "Описание"
|
||||||
|
|
||||||
@ -818,7 +819,7 @@ msgstr ""
|
|||||||
msgid "Desired number of replicas"
|
msgid "Desired number of replicas"
|
||||||
msgstr "Нужный уровень реплик"
|
msgstr "Нужный уровень реплик"
|
||||||
|
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:64
|
#: src/renderer/components/cluster-manager/clusters-menu.tsx:65
|
||||||
msgid "Disconnect"
|
msgid "Disconnect"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -832,7 +833,7 @@ msgstr "Диск"
|
|||||||
msgid "Disk:"
|
msgid "Disk:"
|
||||||
msgstr "Диск:"
|
msgstr "Диск:"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:158
|
#: src/renderer/components/+preferences/preferences.tsx:165
|
||||||
msgid "Does not affect cluster communications!"
|
msgid "Does not affect cluster communications!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -841,14 +842,22 @@ msgid "Domains"
|
|||||||
msgstr "Домены"
|
msgstr "Домены"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:129
|
#: src/renderer/components/+preferences/preferences.tsx:129
|
||||||
msgid "Download Mirror"
|
#~ msgid "Download Mirror"
|
||||||
msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/kubeconfig-dialog/kubeconfig-dialog.tsx:90
|
#: src/renderer/components/kubeconfig-dialog/kubeconfig-dialog.tsx:90
|
||||||
msgid "Download file"
|
msgid "Download file"
|
||||||
msgstr "Скачать файл"
|
msgstr "Скачать файл"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:130
|
#: src/renderer/components/+preferences/kubectl-binaries.tsx:39
|
||||||
|
msgid "Download kubectl binaries"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/renderer/components/+preferences/kubectl-binaries.tsx:37
|
||||||
|
msgid "Download kubectl binaries matching to Kubernetes cluster verison."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/renderer/components/+preferences/kubectl-binaries.tsx:41
|
||||||
msgid "Download mirror for kubectl"
|
msgid "Download mirror for kubectl"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -874,7 +883,7 @@ msgstr "Продолжительность"
|
|||||||
msgid "E-mail"
|
msgid "E-mail"
|
||||||
msgstr "Эл. почта"
|
msgstr "Эл. почта"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:112
|
#: src/renderer/components/+workspaces/workspaces.tsx:125
|
||||||
#: src/renderer/components/menu/menu-actions.tsx:80
|
#: src/renderer/components/menu/menu-actions.tsx:80
|
||||||
#: src/renderer/components/menu/menu-actions.tsx:81
|
#: src/renderer/components/menu/menu-actions.tsx:81
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@ -1001,7 +1010,7 @@ msgstr "От <0>{from}</0> до <1>{to}</1>"
|
|||||||
msgid "Fs Group"
|
msgid "Fs Group"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+landing-page/landing-page.tsx:23
|
#: src/renderer/components/+landing-page/landing-page.tsx:37
|
||||||
msgid "Get started by associating one or more clusters to Lens."
|
msgid "Get started by associating one or more clusters to Lens."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1023,7 +1032,7 @@ msgstr "Группы"
|
|||||||
msgid "HPA"
|
msgid "HPA"
|
||||||
msgstr "HPA"
|
msgstr "HPA"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:147
|
#: src/renderer/components/+preferences/preferences.tsx:137
|
||||||
msgid "HTTP Proxy"
|
msgid "HTTP Proxy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1031,7 +1040,7 @@ msgstr ""
|
|||||||
#~ msgid "HTTP Proxy server. Used for communicating with Kubernetes API."
|
#~ msgid "HTTP Proxy server. Used for communicating with Kubernetes API."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:132
|
#: src/renderer/components/+preferences/preferences.tsx:145
|
||||||
msgid "Helm"
|
msgid "Helm"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1051,7 +1060,7 @@ msgstr "Helm установка: {repo}/{name}"
|
|||||||
msgid "Helm Upgrade: {0}"
|
msgid "Helm Upgrade: {0}"
|
||||||
msgstr "Helm обновление: {0}"
|
msgstr "Helm обновление: {0}"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:47
|
#: src/renderer/components/+preferences/preferences.tsx:51
|
||||||
msgid "Helm branch <0>{0}</0> already in use"
|
msgid "Helm branch <0>{0}</0> already in use"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1158,11 +1167,11 @@ msgstr "Установка завершена!"
|
|||||||
msgid "Installing..."
|
msgid "Installing..."
|
||||||
msgstr "Установка.."
|
msgstr "Установка.."
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:44
|
#: src/renderer/components/input/input.validators.ts:50
|
||||||
msgid "Invalid account ID"
|
msgid "Invalid account ID"
|
||||||
msgstr "Неверный ID аккаунта"
|
msgstr "Неверный ID аккаунта"
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:15
|
#: src/renderer/components/input/input.validators.ts:16
|
||||||
msgid "Invalid number"
|
msgid "Invalid number"
|
||||||
msgstr "Неверный номер"
|
msgstr "Неверный номер"
|
||||||
|
|
||||||
@ -1198,7 +1207,6 @@ msgstr ""
|
|||||||
#: src/renderer/components/+workloads/workloads.tsx:69
|
#: src/renderer/components/+workloads/workloads.tsx:69
|
||||||
#: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:62
|
#: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:62
|
||||||
#: src/renderer/components/+workloads-jobs/jobs.tsx:36
|
#: src/renderer/components/+workloads-jobs/jobs.tsx:36
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:62
|
|
||||||
msgid "Jobs"
|
msgid "Jobs"
|
||||||
msgstr "Jobs"
|
msgstr "Jobs"
|
||||||
|
|
||||||
@ -1242,6 +1250,10 @@ msgstr "Файл конфигурации"
|
|||||||
msgid "Kubeconfig File"
|
msgid "Kubeconfig File"
|
||||||
msgstr "Файл конфигурации"
|
msgstr "Файл конфигурации"
|
||||||
|
|
||||||
|
#: src/renderer/components/+preferences/kubectl-binaries.tsx:35
|
||||||
|
msgid "Kubectl Binary"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+nodes/node-details.tsx:98
|
#: src/renderer/components/+nodes/node-details.tsx:98
|
||||||
msgid "Kubelet version"
|
msgid "Kubelet version"
|
||||||
msgstr "Версия Kubelet"
|
msgstr "Версия Kubelet"
|
||||||
@ -1358,7 +1370,7 @@ msgstr "Макс. подов"
|
|||||||
msgid "Max Unavailable"
|
msgid "Max Unavailable"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:35
|
#: src/renderer/components/input/input.validators.ts:41
|
||||||
msgid "Maximum length is {maxLength}"
|
msgid "Maximum length is {maxLength}"
|
||||||
msgstr "Максимальная длина {maxLength}"
|
msgstr "Максимальная длина {maxLength}"
|
||||||
|
|
||||||
@ -1434,7 +1446,7 @@ msgstr "Мин. подов"
|
|||||||
msgid "Minimize"
|
msgid "Minimize"
|
||||||
msgstr "Минимизировать"
|
msgstr "Минимизировать"
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:30
|
#: src/renderer/components/input/input.validators.ts:36
|
||||||
msgid "Minimum length is {minLength}"
|
msgid "Minimum length is {minLength}"
|
||||||
msgstr "Минимальная длина {minLength}"
|
msgstr "Минимальная длина {minLength}"
|
||||||
|
|
||||||
@ -1498,7 +1510,7 @@ msgstr "Установки"
|
|||||||
#: src/renderer/components/+workloads-pods/pods.tsx:74
|
#: src/renderer/components/+workloads-pods/pods.tsx:74
|
||||||
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:50
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:50
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulsets.tsx:40
|
#: src/renderer/components/+workloads-statefulsets/statefulsets.tsx:40
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:117
|
#: src/renderer/components/+workspaces/workspaces.tsx:130
|
||||||
#: src/renderer/components/dock/edit-resource.tsx:90
|
#: src/renderer/components/dock/edit-resource.tsx:90
|
||||||
#: src/renderer/components/kube-object/kube-object-meta.tsx:20
|
#: src/renderer/components/kube-object/kube-object-meta.tsx:20
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
@ -1566,7 +1578,7 @@ msgstr "Namespaces"
|
|||||||
msgid "Namespaces: {0}"
|
msgid "Namespaces: {0}"
|
||||||
msgstr "Namespaces: {0}"
|
msgstr "Namespaces: {0}"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:157
|
#: src/renderer/components/+preferences/preferences.tsx:164
|
||||||
msgid "Needed with some corporate proxies that do certificate re-writing."
|
msgid "Needed with some corporate proxies that do certificate re-writing."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1627,7 +1639,7 @@ msgstr "Нет доступных нод."
|
|||||||
#~ msgid "No contexts available or they already added"
|
#~ msgid "No contexts available or they already added"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:275
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:260
|
||||||
msgid "No contexts available or they have been added already"
|
msgid "No contexts available or they have been added already"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1743,7 +1755,7 @@ msgid "Organization"
|
|||||||
msgstr "Организация"
|
msgstr "Организация"
|
||||||
|
|
||||||
#: src/renderer/components/+workloads/workloads.tsx:29
|
#: src/renderer/components/+workloads/workloads.tsx:29
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:35
|
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:45
|
||||||
msgid "Overview"
|
msgid "Overview"
|
||||||
msgstr "Обзор"
|
msgstr "Обзор"
|
||||||
|
|
||||||
@ -1759,7 +1771,7 @@ msgstr "Параллелизм"
|
|||||||
msgid "Parameters"
|
msgid "Parameters"
|
||||||
msgstr "Параметры"
|
msgstr "Параметры"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:245
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:230
|
||||||
msgid "Paste as text"
|
msgid "Paste as text"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1849,7 +1861,6 @@ msgstr "Командная строка пода"
|
|||||||
#: src/renderer/components/+workloads/workloads.tsx:37
|
#: src/renderer/components/+workloads/workloads.tsx:37
|
||||||
#: src/renderer/components/+workloads-daemonsets/daemonsets.tsx:47
|
#: src/renderer/components/+workloads-daemonsets/daemonsets.tsx:47
|
||||||
#: src/renderer/components/+workloads-deployments/deployments.tsx:60
|
#: src/renderer/components/+workloads-deployments/deployments.tsx:60
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:42
|
|
||||||
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:89
|
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:89
|
||||||
#: src/renderer/components/+workloads-pods/pods.tsx:73
|
#: src/renderer/components/+workloads-pods/pods.tsx:73
|
||||||
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:52
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:52
|
||||||
@ -1900,7 +1911,7 @@ msgstr ""
|
|||||||
#~ msgid "Pro-Tip: paste kubeconfig to collect available contexts"
|
#~ msgid "Pro-Tip: paste kubeconfig to collect available contexts"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:263
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:248
|
||||||
msgid "Pro-Tip: paste kubeconfig to get available contexts"
|
msgid "Pro-Tip: paste kubeconfig to get available contexts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1908,7 +1919,7 @@ msgstr ""
|
|||||||
#~ msgid "Pro-Tip: paste kubeconfig to parse available contexts"
|
#~ msgid "Pro-Tip: paste kubeconfig to parse available contexts"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:254
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:239
|
||||||
msgid "Pro-Tip: you can also drag-n-drop kubeconfig file to this area"
|
msgid "Pro-Tip: you can also drag-n-drop kubeconfig file to this area"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1925,11 +1936,11 @@ msgstr ""
|
|||||||
msgid "Provisioner"
|
msgid "Provisioner"
|
||||||
msgstr "Комиссия"
|
msgstr "Комиссия"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:150
|
#: src/renderer/components/+preferences/preferences.tsx:140
|
||||||
msgid "Proxy is used only for non-cluster communication."
|
msgid "Proxy is used only for non-cluster communication."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:308
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:293
|
||||||
msgid "Proxy settings"
|
msgid "Proxy settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2009,10 +2020,10 @@ msgstr "Установка: {0}"
|
|||||||
msgid "Releases"
|
msgid "Releases"
|
||||||
msgstr "Релизы"
|
msgstr "Релизы"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:139
|
#: src/renderer/components/+preferences/preferences.tsx:152
|
||||||
#: src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx:60
|
#: src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx:60
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:74
|
#: src/renderer/components/cluster-manager/clusters-menu.tsx:76
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:80
|
#: src/renderer/components/cluster-manager/clusters-menu.tsx:82
|
||||||
#: src/renderer/components/item-object-list/item-list-layout.tsx:179
|
#: src/renderer/components/item-object-list/item-list-layout.tsx:179
|
||||||
#: src/renderer/components/menu/menu-actions.tsx:49
|
#: src/renderer/components/menu/menu-actions.tsx:49
|
||||||
#: src/renderer/components/menu/menu-actions.tsx:85
|
#: src/renderer/components/menu/menu-actions.tsx:85
|
||||||
@ -2023,7 +2034,7 @@ msgstr "Удалить"
|
|||||||
msgid "Remove <0>{releaseNames}</0>?"
|
msgid "Remove <0>{releaseNames}</0>?"
|
||||||
msgstr "Удалить <0>{releaseNames}</0>?"
|
msgstr "Удалить <0>{releaseNames}</0>?"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:51
|
#: src/renderer/components/+workspaces/workspaces.tsx:52
|
||||||
msgid "Remove Workspace"
|
msgid "Remove Workspace"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2051,7 +2062,7 @@ msgstr "Удалить выбранные элементы ({0})"
|
|||||||
msgid "Remove {resourceKind} <0>{resourceName}</0>?"
|
msgid "Remove {resourceKind} <0>{resourceName}</0>?"
|
||||||
msgstr "Удалить {resourceKind} <0>{resourceName}</0>?"
|
msgstr "Удалить {resourceKind} <0>{resourceName}</0>?"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:114
|
#: src/renderer/components/+preferences/preferences.tsx:122
|
||||||
msgid "Removing helm branch <0>{0}</0> has failed: {1}"
|
msgid "Removing helm branch <0>{0}</0> has failed: {1}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2075,7 +2086,7 @@ msgstr "Реплики"
|
|||||||
msgid "Repo/Name"
|
msgid "Repo/Name"
|
||||||
msgstr "Репозиторий/Имя"
|
msgstr "Репозиторий/Имя"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:133
|
#: src/renderer/components/+preferences/preferences.tsx:146
|
||||||
msgid "Repositories"
|
msgid "Repositories"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2110,7 +2121,7 @@ msgstr ""
|
|||||||
msgid "Required field"
|
msgid "Required field"
|
||||||
msgstr "Обязательное поле"
|
msgstr "Обязательное поле"
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:250
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:235
|
||||||
#: src/renderer/components/item-object-list/page-filters-list.tsx:31
|
#: src/renderer/components/item-object-list/page-filters-list.tsx:31
|
||||||
msgid "Reset"
|
msgid "Reset"
|
||||||
msgstr "Сбросить"
|
msgstr "Сбросить"
|
||||||
@ -2253,7 +2264,7 @@ msgstr ""
|
|||||||
#: src/renderer/components/+config-maps/config-map-details.tsx:78
|
#: src/renderer/components/+config-maps/config-map-details.tsx:78
|
||||||
#: src/renderer/components/+config-secrets/secret-details.tsx:97
|
#: src/renderer/components/+config-secrets/secret-details.tsx:97
|
||||||
#: src/renderer/components/+workloads-pods/pod-logs-dialog.tsx:216
|
#: src/renderer/components/+workloads-pods/pod-logs-dialog.tsx:216
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:120
|
#: src/renderer/components/+workspaces/workspaces.tsx:132
|
||||||
#: src/renderer/components/dock/edit-resource.tsx:88
|
#: src/renderer/components/dock/edit-resource.tsx:88
|
||||||
msgid "Save"
|
msgid "Save"
|
||||||
msgstr "Сохранить"
|
msgstr "Сохранить"
|
||||||
@ -2342,13 +2353,13 @@ msgstr "Выберите квоту..."
|
|||||||
#~ msgid "Select context(s)"
|
#~ msgid "Select context(s)"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:272
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:257
|
||||||
#~ msgid "Select contexts"
|
msgid "Select contexts"
|
||||||
#~ msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:272
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:272
|
||||||
msgid "Select contexts (available: {0})"
|
#~ msgid "Select contexts (available: {0})"
|
||||||
msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:76
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:76
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:76
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:76
|
||||||
@ -2372,7 +2383,7 @@ msgstr ""
|
|||||||
#~ msgid "Select kubeconfig"
|
#~ msgid "Select kubeconfig"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:244
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:229
|
||||||
msgid "Select kubeconfig file"
|
msgid "Select kubeconfig file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2400,7 +2411,7 @@ msgstr "Выбрать сервисные аккаунты"
|
|||||||
#~ msgid "Selected contexts ({0}): <0>{1}</0>"
|
#~ msgid "Selected contexts ({0}): <0>{1}</0>"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+add-cluster/add-cluster.tsx:271
|
#: src/renderer/components/+add-cluster/add-cluster.tsx:256
|
||||||
msgid "Selected contexts: <0>{0}</0>"
|
msgid "Selected contexts: <0>{0}</0>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2504,7 +2515,6 @@ msgid "Stateful Sets"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workloads/workloads.tsx:61
|
#: src/renderer/components/+workloads/workloads.tsx:61
|
||||||
#: src/renderer/components/+workloads-overview/overview-statuses.tsx:52
|
|
||||||
msgid "StatefulSets"
|
msgid "StatefulSets"
|
||||||
msgstr "StatefulSets"
|
msgstr "StatefulSets"
|
||||||
|
|
||||||
@ -2606,11 +2616,11 @@ msgstr "TLS"
|
|||||||
msgid "Taints"
|
msgid "Taints"
|
||||||
msgstr "Метки блокировки"
|
msgstr "Метки блокировки"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:161
|
#: src/renderer/components/+preferences/preferences.tsx:168
|
||||||
msgid "Telemetry & Usage Tracking"
|
msgid "Telemetry & Usage Tracking"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:164
|
#: src/renderer/components/+preferences/preferences.tsx:171
|
||||||
msgid "Telemetry & usage data is collected to continuously improve the Lens experience."
|
msgid "Telemetry & usage data is collected to continuously improve the Lens experience."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2630,15 +2640,19 @@ msgstr "Для контейнера нет логов."
|
|||||||
msgid "There are no logs available."
|
msgid "There are no logs available."
|
||||||
msgstr "Логи отсутствуют."
|
msgstr "Логи отсутствуют."
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:5
|
#: src/renderer/components/input/input.validators.ts:6
|
||||||
msgid "This field is required"
|
msgid "This field is required"
|
||||||
msgstr "Это обязательное поле"
|
msgstr "Это обязательное поле"
|
||||||
|
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:106
|
#: src/renderer/components/input/input.validators.ts:31
|
||||||
|
msgid "This field must be a valid path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/renderer/components/+landing-page/landing-page.tsx:25
|
||||||
msgid "This is the quick launch menu."
|
msgid "This is the quick launch menu."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:156
|
#: src/renderer/components/+preferences/preferences.tsx:163
|
||||||
msgid "This will make Lens to trust ANY certificate authority without any validations."
|
msgid "This will make Lens to trust ANY certificate authority without any validations."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2662,13 +2676,13 @@ msgstr "Толерантности"
|
|||||||
msgid "Transmit"
|
msgid "Transmit"
|
||||||
msgstr "Транзит"
|
msgstr "Транзит"
|
||||||
|
|
||||||
#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:107
|
#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:106
|
||||||
#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:79
|
#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:79
|
||||||
#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:80
|
#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:80
|
||||||
msgid "Trigger"
|
msgid "Trigger"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:103
|
#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:102
|
||||||
msgid "Trigger CronJob <0>{cronjobName}</0>"
|
msgid "Trigger CronJob <0>{cronjobName}</0>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2691,7 +2705,7 @@ msgstr ""
|
|||||||
msgid "Type"
|
msgid "Type"
|
||||||
msgstr "Тип"
|
msgstr "Тип"
|
||||||
|
|
||||||
#: src/renderer/components/+preferences/preferences.tsx:148
|
#: src/renderer/components/+preferences/preferences.tsx:138
|
||||||
msgid "Type HTTP proxy url (example: http://proxy.acme.org:8080)"
|
msgid "Type HTTP proxy url (example: http://proxy.acme.org:8080)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2828,11 +2842,11 @@ msgstr "Ожидание запуска сервисов"
|
|||||||
msgid "Warnings: {0}"
|
msgid "Warnings: {0}"
|
||||||
msgstr "Предупреждения: {0}"
|
msgstr "Предупреждения: {0}"
|
||||||
|
|
||||||
#: src/renderer/components/+landing-page/landing-page.tsx:20
|
#: src/renderer/components/+landing-page/landing-page.tsx:34
|
||||||
msgid "Welcome!"
|
msgid "Welcome!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:79
|
#: src/renderer/components/+workspaces/workspaces.tsx:88
|
||||||
msgid "What is a Workspace?"
|
msgid "What is a Workspace?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2845,19 +2859,19 @@ msgid "Workloads"
|
|||||||
msgstr "Ресурсы"
|
msgstr "Ресурсы"
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspace-menu.tsx:39
|
#: src/renderer/components/+workspaces/workspace-menu.tsx:39
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:91
|
#: src/renderer/components/+workspaces/workspaces.tsx:100
|
||||||
msgid "Workspaces"
|
msgid "Workspaces"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workspaces/workspaces.tsx:81
|
#: src/renderer/components/+workspaces/workspaces.tsx:90
|
||||||
msgid "Workspaces are used to organize number of clusters into logical groups."
|
msgid "Workspaces are used to organize number of clusters into logical groups."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:10
|
#: src/renderer/components/input/input.validators.ts:11
|
||||||
msgid "Wrong email format"
|
msgid "Wrong email format"
|
||||||
msgstr "Неверный формат электронной почты"
|
msgstr "Неверный формат электронной почты"
|
||||||
|
|
||||||
#: src/renderer/components/input/input.validators.ts:25
|
#: src/renderer/components/input/input.validators.ts:26
|
||||||
msgid "Wrong url format"
|
msgid "Wrong url format"
|
||||||
msgstr "Неверный url формат"
|
msgstr "Неверный url формат"
|
||||||
|
|
||||||
@ -2916,7 +2930,7 @@ msgstr ""
|
|||||||
msgid "never"
|
msgid "never"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/cluster-manager/clusters-menu.tsx:121
|
#: src/renderer/components/cluster-manager/clusters-menu.tsx:133
|
||||||
msgid "new"
|
msgid "new"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
"name": "kontena-lens",
|
"name": "kontena-lens",
|
||||||
"productName": "Lens",
|
"productName": "Lens",
|
||||||
"description": "Lens - The Kubernetes IDE",
|
"description": "Lens - The Kubernetes IDE",
|
||||||
"version": "3.6.4",
|
"version": "3.6.5-rc.1",
|
||||||
"main": "static/build/main.js",
|
"main": "static/build/main.js",
|
||||||
"copyright": "© 2020, Mirantis, Inc.",
|
"copyright": "© 2020, Mirantis, Inc.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -39,7 +39,7 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"bundledKubectlVersion": "1.17.11",
|
"bundledKubectlVersion": "1.17.11",
|
||||||
"bundledHelmVersion": "3.3.1"
|
"bundledHelmVersion": "3.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12.0 <13.0"
|
"node": ">=12.0 <13.0"
|
||||||
|
|||||||
@ -93,6 +93,10 @@ export class BaseStore<T = any> extends Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unregisterIpcListener() {
|
||||||
|
ipcRenderer.removeAllListeners(this.syncChannel)
|
||||||
|
}
|
||||||
|
|
||||||
disableSync() {
|
disableSync() {
|
||||||
this.syncDisposers.forEach(dispose => dispose());
|
this.syncDisposers.forEach(dispose => dispose());
|
||||||
this.syncDisposers.length = 0;
|
this.syncDisposers.length = 0;
|
||||||
|
|||||||
@ -9,7 +9,7 @@ export const clusterIpc = {
|
|||||||
const cluster = clusterStore.getById(clusterId);
|
const cluster = clusterStore.getById(clusterId);
|
||||||
if (cluster) {
|
if (cluster) {
|
||||||
if (frameId) cluster.frameId = frameId; // save cluster's webFrame.routingId to be able to send push-updates
|
if (frameId) cluster.frameId = frameId; // save cluster's webFrame.routingId to be able to send push-updates
|
||||||
return cluster.activate(true);
|
return cluster.activate();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import type { WorkspaceId } from "./workspace-store";
|
import type { WorkspaceId } from "./workspace-store";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { app, ipcRenderer, remote } from "electron";
|
import { app, ipcRenderer, remote, webFrame, webContents } from "electron";
|
||||||
import { unlink } from "fs-extra";
|
import { unlink } from "fs-extra";
|
||||||
import { action, computed, observable, toJS } from "mobx";
|
import { action, computed, observable, toJS } from "mobx";
|
||||||
import { BaseStore } from "./base-store";
|
import { BaseStore } from "./base-store";
|
||||||
@ -73,20 +73,27 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
|||||||
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
|
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
|
||||||
migrations: migrations,
|
migrations: migrations,
|
||||||
});
|
});
|
||||||
if (ipcRenderer) {
|
|
||||||
ipcRenderer.on("cluster:state", (event, model: ClusterState) => {
|
|
||||||
this.applyWithoutSync(() => {
|
|
||||||
logger.silly(`[CLUSTER-STORE]: received push-state at ${location.host}`, model);
|
|
||||||
this.getById(model.id)?.updateModel(model);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@observable activeClusterId: ClusterId;
|
@observable activeClusterId: ClusterId;
|
||||||
@observable removedClusters = observable.map<ClusterId, Cluster>();
|
@observable removedClusters = observable.map<ClusterId, Cluster>();
|
||||||
@observable clusters = observable.map<ClusterId, Cluster>();
|
@observable clusters = observable.map<ClusterId, Cluster>();
|
||||||
|
|
||||||
|
registerIpcListener() {
|
||||||
|
logger.info(`[CLUSTER-STORE] start to listen (${webFrame.routingId})`)
|
||||||
|
ipcRenderer.on("cluster:state", (event, model: ClusterState) => {
|
||||||
|
this.applyWithoutSync(() => {
|
||||||
|
logger.silly(`[CLUSTER-STORE]: received push-state at ${location.host} (${webFrame.routingId})`, model);
|
||||||
|
this.getById(model.id)?.updateModel(model);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
unregisterIpcListener() {
|
||||||
|
super.unregisterIpcListener()
|
||||||
|
ipcRenderer.removeAllListeners("cluster:state")
|
||||||
|
}
|
||||||
|
|
||||||
@computed get activeCluster(): Cluster | null {
|
@computed get activeCluster(): Cluster | null {
|
||||||
return this.getById(this.activeClusterId);
|
return this.getById(this.activeClusterId);
|
||||||
}
|
}
|
||||||
@ -122,10 +129,6 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
|||||||
return this.clusters.size > 0;
|
return this.clusters.size > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hasContext(name: string) {
|
|
||||||
return this.clustersList.some(cluster => cluster.contextName === name);
|
|
||||||
}
|
|
||||||
|
|
||||||
getById(id: ClusterId): Cluster {
|
getById(id: ClusterId): Cluster {
|
||||||
return this.clusters.get(id);
|
return this.clusters.get(id);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -146,14 +146,22 @@ describe("config with existing clusters", () => {
|
|||||||
id: 'cluster1',
|
id: 'cluster1',
|
||||||
kubeConfig: 'foo',
|
kubeConfig: 'foo',
|
||||||
contextName: 'foo',
|
contextName: 'foo',
|
||||||
preferences: { terminalCWD: '/foo' }
|
preferences: { terminalCWD: '/foo' },
|
||||||
|
workspace: 'default'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'cluster2',
|
id: 'cluster2',
|
||||||
kubeConfig: 'foo2',
|
kubeConfig: 'foo2',
|
||||||
contextName: 'foo2',
|
contextName: 'foo2',
|
||||||
preferences: { terminalCWD: '/foo2' }
|
preferences: { terminalCWD: '/foo2' }
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
id: 'cluster3',
|
||||||
|
kubeConfig: 'foo',
|
||||||
|
contextName: 'foo',
|
||||||
|
preferences: { terminalCWD: '/foo' },
|
||||||
|
workspace: 'foo'
|
||||||
|
},
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -183,10 +191,12 @@ describe("config with existing clusters", () => {
|
|||||||
|
|
||||||
it("allows getting all of the clusters", async () => {
|
it("allows getting all of the clusters", async () => {
|
||||||
const storedClusters = clusterStore.clustersList;
|
const storedClusters = clusterStore.clustersList;
|
||||||
|
expect(storedClusters.length).toBe(3)
|
||||||
expect(storedClusters[0].id).toBe('cluster1')
|
expect(storedClusters[0].id).toBe('cluster1')
|
||||||
expect(storedClusters[0].preferences.terminalCWD).toBe('/foo')
|
expect(storedClusters[0].preferences.terminalCWD).toBe('/foo')
|
||||||
expect(storedClusters[1].id).toBe('cluster2')
|
expect(storedClusters[1].id).toBe('cluster2')
|
||||||
expect(storedClusters[1].preferences.terminalCWD).toBe('/foo2')
|
expect(storedClusters[1].preferences.terminalCWD).toBe('/foo2')
|
||||||
|
expect(storedClusters[2].id).toBe('cluster3')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import { PrometheusLens } from "../main/prometheus/lens";
|
import { PrometheusLens } from "../main/prometheus/lens";
|
||||||
import { PrometheusHelm } from "../main/prometheus/helm";
|
import { PrometheusHelm } from "../main/prometheus/helm";
|
||||||
import { PrometheusOperator } from "../main/prometheus/operator";
|
import { PrometheusOperator } from "../main/prometheus/operator";
|
||||||
|
import { PrometheusStacklight } from "../main/prometheus/stacklight";
|
||||||
import { PrometheusProviderRegistry } from "../main/prometheus/provider-registry";
|
import { PrometheusProviderRegistry } from "../main/prometheus/provider-registry";
|
||||||
|
|
||||||
[PrometheusLens, PrometheusHelm, PrometheusOperator].forEach(providerClass => {
|
[PrometheusLens, PrometheusHelm, PrometheusOperator, PrometheusStacklight].forEach(providerClass => {
|
||||||
const provider = new providerClass()
|
const provider = new providerClass()
|
||||||
PrometheusProviderRegistry.registerProvider(provider.id, provider)
|
PrometheusProviderRegistry.registerProvider(provider.id, provider)
|
||||||
});
|
});
|
||||||
|
|||||||
@ -59,8 +59,6 @@ export class UserStore extends BaseStore<UserStoreModel> {
|
|||||||
colorTheme: UserStore.defaultTheme,
|
colorTheme: UserStore.defaultTheme,
|
||||||
downloadMirror: "default",
|
downloadMirror: "default",
|
||||||
downloadKubectlBinaries: true, // Download kubectl binaries matching cluster version
|
downloadKubectlBinaries: true, // Download kubectl binaries matching cluster version
|
||||||
downloadBinariesPath: this.getDefaultKubectlPath(),
|
|
||||||
kubectlBinariesPath: ""
|
|
||||||
};
|
};
|
||||||
|
|
||||||
get isNewVersion() {
|
get isNewVersion() {
|
||||||
|
|||||||
@ -56,10 +56,10 @@ export class Cluster implements ClusterModel {
|
|||||||
@observable kubeConfigPath: string;
|
@observable kubeConfigPath: string;
|
||||||
@observable apiUrl: string; // cluster server url
|
@observable apiUrl: string; // cluster server url
|
||||||
@observable kubeProxyUrl: string; // lens-proxy to kube-api url
|
@observable kubeProxyUrl: string; // lens-proxy to kube-api url
|
||||||
@observable online: boolean;
|
@observable online = false;
|
||||||
@observable accessible: boolean;
|
@observable accessible = false;
|
||||||
@observable ready: boolean;
|
@observable ready = false;
|
||||||
@observable disconnected: boolean;
|
@observable disconnected = true;
|
||||||
@observable failureReason: string;
|
@observable failureReason: string;
|
||||||
@observable nodes = 0;
|
@observable nodes = 0;
|
||||||
@observable version: string;
|
@observable version: string;
|
||||||
@ -124,13 +124,14 @@ export class Cluster implements ClusterModel {
|
|||||||
this.eventDisposers.length = 0;
|
this.eventDisposers.length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
async activate(init = false) {
|
@action
|
||||||
|
async activate() {
|
||||||
logger.info(`[CLUSTER]: activate`, this.getMeta());
|
logger.info(`[CLUSTER]: activate`, this.getMeta());
|
||||||
await this.whenInitialized;
|
await this.whenInitialized;
|
||||||
if (!this.eventDisposers.length) {
|
if (!this.eventDisposers.length) {
|
||||||
this.bindEvents();
|
this.bindEvents();
|
||||||
}
|
}
|
||||||
if (this.disconnected || (!init && !this.accessible)) {
|
if (this.disconnected || !this.accessible) {
|
||||||
await this.reconnect();
|
await this.reconnect();
|
||||||
}
|
}
|
||||||
await this.refreshConnectionStatus()
|
await this.refreshConnectionStatus()
|
||||||
@ -143,6 +144,7 @@ export class Cluster implements ClusterModel {
|
|||||||
return this.pushState();
|
return this.pushState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
async reconnect() {
|
async reconnect() {
|
||||||
logger.info(`[CLUSTER]: reconnect`, this.getMeta());
|
logger.info(`[CLUSTER]: reconnect`, this.getMeta());
|
||||||
this.contextHandler.stopServer();
|
this.contextHandler.stopServer();
|
||||||
|
|||||||
@ -36,7 +36,7 @@ const packageMirrors: Map<string, string> = new Map([
|
|||||||
let bundledPath: string
|
let bundledPath: string
|
||||||
const initScriptVersionString = "# lens-initscript v3\n"
|
const initScriptVersionString = "# lens-initscript v3\n"
|
||||||
|
|
||||||
if (isDevelopment || isTestEnv) {
|
if (isDevelopment || isTestEnv) {
|
||||||
const platformName = isWindows ? "windows" : process.platform
|
const platformName = isWindows ? "windows" : process.platform
|
||||||
bundledPath = path.join(process.cwd(), "binaries", "client", platformName, process.arch, "kubectl")
|
bundledPath = path.join(process.cwd(), "binaries", "client", platformName, process.arch, "kubectl")
|
||||||
} else {
|
} else {
|
||||||
@ -110,7 +110,11 @@ export class Kubectl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected getDownloadDir() {
|
protected getDownloadDir() {
|
||||||
return userStore.preferences?.downloadBinariesPath || Kubectl.kubectlDir
|
if (userStore.preferences?.downloadBinariesPath) {
|
||||||
|
return path.join(userStore.preferences.downloadBinariesPath, "kubectl")
|
||||||
|
}
|
||||||
|
|
||||||
|
return Kubectl.kubectlDir
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getPath(bundled = false): Promise<string> {
|
public async getPath(bundled = false): Promise<string> {
|
||||||
@ -214,7 +218,7 @@ export class Kubectl {
|
|||||||
});
|
});
|
||||||
isValid = !await this.checkBinary(this.path, false)
|
isValid = !await this.checkBinary(this.path, false)
|
||||||
}
|
}
|
||||||
if(!isValid) {
|
if (!isValid) {
|
||||||
logger.debug(`Releasing lock for ${this.kubectlVersion}`)
|
logger.debug(`Releasing lock for ${this.kubectlVersion}`)
|
||||||
release()
|
release()
|
||||||
return false
|
return false
|
||||||
@ -279,6 +283,12 @@ export class Kubectl {
|
|||||||
bashScript += "fi\n"
|
bashScript += "fi\n"
|
||||||
bashScript += `export PATH="${helmPath}:${kubectlPath}:$PATH"\n`
|
bashScript += `export PATH="${helmPath}:${kubectlPath}:$PATH"\n`
|
||||||
bashScript += "export KUBECONFIG=\"$tempkubeconfig\"\n"
|
bashScript += "export KUBECONFIG=\"$tempkubeconfig\"\n"
|
||||||
|
|
||||||
|
bashScript += "NO_PROXY=\",${NO_PROXY:-localhost},\"\n"
|
||||||
|
bashScript += "NO_PROXY=\"${NO_PROXY//,localhost,/,}\"\n"
|
||||||
|
bashScript += "NO_PROXY=\"${NO_PROXY//,127.0.0.1,/,}\"\n"
|
||||||
|
bashScript += "NO_PROXY=\"localhost,127.0.0.1${NO_PROXY%,}\"\n"
|
||||||
|
bashScript += "export NO_PROXY\n"
|
||||||
bashScript += "unset tempkubeconfig\n"
|
bashScript += "unset tempkubeconfig\n"
|
||||||
await fsPromises.writeFile(bashScriptPath, bashScript.toString(), { mode: 0o644 })
|
await fsPromises.writeFile(bashScriptPath, bashScript.toString(), { mode: 0o644 })
|
||||||
|
|
||||||
@ -304,6 +314,11 @@ export class Kubectl {
|
|||||||
zshScript += "d=${d/#:/}\n"
|
zshScript += "d=${d/#:/}\n"
|
||||||
zshScript += "export PATH=\"$helmpath:$kubectlpath:${d/%:/}\"\n"
|
zshScript += "export PATH=\"$helmpath:$kubectlpath:${d/%:/}\"\n"
|
||||||
zshScript += "export KUBECONFIG=\"$tempkubeconfig\"\n"
|
zshScript += "export KUBECONFIG=\"$tempkubeconfig\"\n"
|
||||||
|
zshScript += "NO_PROXY=\",${NO_PROXY:-localhost},\"\n"
|
||||||
|
zshScript += "NO_PROXY=\"${NO_PROXY//,localhost,/,}\"\n"
|
||||||
|
zshScript += "NO_PROXY=\"${NO_PROXY//,127.0.0.1,/,}\"\n"
|
||||||
|
zshScript += "NO_PROXY=\"localhost,127.0.0.1${NO_PROXY%,}\"\n"
|
||||||
|
zshScript += "export NO_PROXY\n"
|
||||||
zshScript += "unset tempkubeconfig\n"
|
zshScript += "unset tempkubeconfig\n"
|
||||||
zshScript += "unset OLD_ZDOTDIR\n"
|
zshScript += "unset OLD_ZDOTDIR\n"
|
||||||
await fsPromises.writeFile(zshScriptPath, zshScript.toString(), { mode: 0o644 })
|
await fsPromises.writeFile(zshScriptPath, zshScript.toString(), { mode: 0o644 })
|
||||||
|
|||||||
@ -44,9 +44,7 @@ export class LensProxy {
|
|||||||
const spdyProxy = spdy.createServer({
|
const spdyProxy = spdy.createServer({
|
||||||
spdy: {
|
spdy: {
|
||||||
plain: true,
|
plain: true,
|
||||||
connection: {
|
protocols: ["http/1.1", "spdy/3.1"]
|
||||||
autoSpdy31: true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, (req: http.IncomingMessage, res: http.ServerResponse) => {
|
}, (req: http.IncomingMessage, res: http.ServerResponse) => {
|
||||||
this.handleRequest(proxy, req, res)
|
this.handleRequest(proxy, req, res)
|
||||||
@ -55,11 +53,7 @@ export class LensProxy {
|
|||||||
if (req.url.startsWith(`${apiPrefix}?`)) {
|
if (req.url.startsWith(`${apiPrefix}?`)) {
|
||||||
this.handleWsUpgrade(req, socket, head)
|
this.handleWsUpgrade(req, socket, head)
|
||||||
} else {
|
} else {
|
||||||
if (req.headers.upgrade?.startsWith("SPDY")) {
|
this.handleProxyUpgrade(proxy, req, socket, head)
|
||||||
this.handleSpdyProxy(proxy, req, socket, head)
|
|
||||||
} else {
|
|
||||||
socket.end()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
spdyProxy.on("error", (err) => {
|
spdyProxy.on("error", (err) => {
|
||||||
@ -68,17 +62,45 @@ export class LensProxy {
|
|||||||
return spdyProxy
|
return spdyProxy
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async handleSpdyProxy(proxy: httpProxy, req: http.IncomingMessage, socket: net.Socket, head: Buffer) {
|
protected async handleProxyUpgrade(proxy: httpProxy, req: http.IncomingMessage, socket: net.Socket, head: Buffer) {
|
||||||
const cluster = this.clusterManager.getClusterForRequest(req)
|
const cluster = this.clusterManager.getClusterForRequest(req)
|
||||||
if (cluster) {
|
if (cluster) {
|
||||||
const proxyUrl = await cluster.contextHandler.resolveAuthProxyUrl() + req.url.replace(apiKubePrefix, "")
|
const proxyUrl = await cluster.contextHandler.resolveAuthProxyUrl() + req.url.replace(apiKubePrefix, "")
|
||||||
const apiUrl = url.parse(cluster.apiUrl)
|
const apiUrl = url.parse(cluster.apiUrl)
|
||||||
const res = new http.ServerResponse(req)
|
const pUrl = url.parse(proxyUrl)
|
||||||
res.assignSocket(socket)
|
const connectOpts = { port: parseInt(pUrl.port), host: pUrl.hostname }
|
||||||
res.setHeader("Location", proxyUrl)
|
const proxySocket = new net.Socket()
|
||||||
res.setHeader("Host", apiUrl.hostname)
|
proxySocket.connect(connectOpts, () => {
|
||||||
res.statusCode = 302
|
proxySocket.write(`${req.method} ${pUrl.path} HTTP/1.1\r\n`)
|
||||||
res.end()
|
proxySocket.write(`Host: ${apiUrl.host}\r\n`)
|
||||||
|
for (let i = 0; i < req.rawHeaders.length; i += 2) {
|
||||||
|
const key = req.rawHeaders[i]
|
||||||
|
if (key !== "Host" && key !== "Authorization") {
|
||||||
|
proxySocket.write(`${req.rawHeaders[i]}: ${req.rawHeaders[i+1]}\r\n`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
proxySocket.write("\r\n")
|
||||||
|
proxySocket.write(head)
|
||||||
|
})
|
||||||
|
proxySocket.on('data', function (chunk) {
|
||||||
|
socket.write(chunk)
|
||||||
|
})
|
||||||
|
proxySocket.on('end', function () {
|
||||||
|
socket.end()
|
||||||
|
})
|
||||||
|
proxySocket.on('error', function (err) {
|
||||||
|
socket.write("HTTP/" + req.httpVersion + " 500 Connection error\r\n\r\n");
|
||||||
|
socket.end()
|
||||||
|
})
|
||||||
|
socket.on('data', function (chunk) {
|
||||||
|
proxySocket.write(chunk)
|
||||||
|
})
|
||||||
|
socket.on('end', function () {
|
||||||
|
proxySocket.end()
|
||||||
|
})
|
||||||
|
socket.on('error', function () {
|
||||||
|
proxySocket.end()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +156,6 @@ export class LensProxy {
|
|||||||
protected async handleRequest(proxy: httpProxy, req: http.IncomingMessage, res: http.ServerResponse) {
|
protected async handleRequest(proxy: httpProxy, req: http.IncomingMessage, res: http.ServerResponse) {
|
||||||
const cluster = this.clusterManager.getClusterForRequest(req)
|
const cluster = this.clusterManager.getClusterForRequest(req)
|
||||||
if (cluster) {
|
if (cluster) {
|
||||||
await cluster.contextHandler.ensureServer();
|
|
||||||
const proxyTarget = await this.getProxyTarget(req, cluster.contextHandler)
|
const proxyTarget = await this.getProxyTarget(req, cluster.contextHandler)
|
||||||
if (proxyTarget) {
|
if (proxyTarget) {
|
||||||
// allow to fetch apis in "clusterId.localhost:port" from "localhost:port"
|
// allow to fetch apis in "clusterId.localhost:port" from "localhost:port"
|
||||||
|
|||||||
@ -37,19 +37,19 @@ export class PrometheusOperator implements PrometheusProvider {
|
|||||||
memoryUsage: `
|
memoryUsage: `
|
||||||
sum(
|
sum(
|
||||||
node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)
|
node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)
|
||||||
) by (node)
|
)
|
||||||
`.replace(/_bytes/g, `_bytes * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"}`),
|
`.replace(/_bytes/g, `_bytes * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"}`),
|
||||||
memoryRequests: `sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="memory"}) by (component)`,
|
memoryRequests: `sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="memory"})`,
|
||||||
memoryLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="memory"}) by (component)`,
|
memoryLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="memory"})`,
|
||||||
memoryCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="memory"}) by (component)`,
|
memoryCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="memory"})`,
|
||||||
cpuUsage: `sum(rate(node_cpu_seconds_total{mode=~"user|system"}[${this.rateAccuracy}])* on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"}) by (node)`,
|
cpuUsage: `sum(rate(node_cpu_seconds_total{mode=~"user|system"}[${this.rateAccuracy}])* on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"})`,
|
||||||
cpuRequests:`sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
|
cpuRequests:`sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="cpu"})`,
|
||||||
cpuLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
|
cpuLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="cpu"})`,
|
||||||
cpuCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
|
cpuCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="cpu"})`,
|
||||||
podUsage: `sum(kubelet_running_pod_count{node=~"${opts.nodes}"})`,
|
podUsage: `sum(kubelet_running_pod_count{node=~"${opts.nodes}"})`,
|
||||||
podCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="pods"}) by (component)`,
|
podCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="pods"})`,
|
||||||
fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"}) by (node)`,
|
fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"})`,
|
||||||
fsUsage: `sum(node_filesystem_size_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"} - node_filesystem_avail_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"}) by (node)`
|
fsUsage: `sum(node_filesystem_size_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"} - node_filesystem_avail_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"})`
|
||||||
}
|
}
|
||||||
case 'nodes':
|
case 'nodes':
|
||||||
return {
|
return {
|
||||||
@ -62,10 +62,10 @@ export class PrometheusOperator implements PrometheusProvider {
|
|||||||
}
|
}
|
||||||
case 'pods':
|
case 'pods':
|
||||||
return {
|
return {
|
||||||
cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
|
cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",image!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
|
||||||
cpuRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
cpuRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||||
cpuLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
cpuLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||||
memoryUsage: `sum(container_memory_working_set_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
memoryUsage: `sum(container_memory_working_set_bytes{container!="POD",container!="",image!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||||
memoryRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
memoryRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||||
memoryLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
memoryLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||||
fsUsage: `sum(container_fs_usage_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
fsUsage: `sum(container_fs_usage_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||||
|
|||||||
83
src/main/prometheus/stacklight.ts
Normal file
83
src/main/prometheus/stacklight.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import { PrometheusProvider, PrometheusQueryOpts, PrometheusQuery, PrometheusService } from "./provider-registry";
|
||||||
|
import { CoreV1Api } from "@kubernetes/client-node";
|
||||||
|
import logger from "../logger"
|
||||||
|
|
||||||
|
export class PrometheusStacklight implements PrometheusProvider {
|
||||||
|
id = "stacklight"
|
||||||
|
name = "Stacklight"
|
||||||
|
rateAccuracy = "1m"
|
||||||
|
|
||||||
|
public async getPrometheusService(client: CoreV1Api): Promise<PrometheusService> {
|
||||||
|
try {
|
||||||
|
const resp = await client.readNamespacedService("prometheus-server", "stacklight")
|
||||||
|
const service = resp.body
|
||||||
|
return {
|
||||||
|
id: this.id,
|
||||||
|
namespace: service.metadata.namespace,
|
||||||
|
service: service.metadata.name,
|
||||||
|
port: service.spec.ports[0].port
|
||||||
|
}
|
||||||
|
} catch(error) {
|
||||||
|
logger.warn(`PrometheusLens: failed to list services: ${error.response.body.message}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getQueries(opts: PrometheusQueryOpts): PrometheusQuery {
|
||||||
|
switch(opts.category) {
|
||||||
|
case 'cluster':
|
||||||
|
return {
|
||||||
|
memoryUsage: `
|
||||||
|
sum(
|
||||||
|
node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)
|
||||||
|
) by (kubernetes_name)
|
||||||
|
`.replace(/_bytes/g, `_bytes{node=~"${opts.nodes}"}`),
|
||||||
|
memoryRequests: `sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="memory"}) by (component)`,
|
||||||
|
memoryLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="memory"}) by (component)`,
|
||||||
|
memoryCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="memory"}) by (component)`,
|
||||||
|
cpuUsage: `sum(rate(node_cpu_seconds_total{node=~"${opts.nodes}", mode=~"user|system"}[${this.rateAccuracy}]))`,
|
||||||
|
cpuRequests:`sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
|
||||||
|
cpuLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
|
||||||
|
cpuCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
|
||||||
|
podUsage: `sum(kubelet_running_pod_count{instance=~"${opts.nodes}"})`,
|
||||||
|
podCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="pods"}) by (component)`,
|
||||||
|
fsSize: `sum(node_filesystem_size_bytes{node=~"${opts.nodes}", mountpoint="/"}) by (node)`,
|
||||||
|
fsUsage: `sum(node_filesystem_size_bytes{node=~"${opts.nodes}", mountpoint="/"} - node_filesystem_avail_bytes{node=~"${opts.nodes}", mountpoint="/"}) by (node)`
|
||||||
|
}
|
||||||
|
case 'nodes':
|
||||||
|
return {
|
||||||
|
memoryUsage: `sum (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (node)`,
|
||||||
|
memoryCapacity: `sum(kube_node_status_capacity{resource="memory"}) by (node)`,
|
||||||
|
cpuUsage: `sum(rate(node_cpu_seconds_total{mode=~"user|system"}[${this.rateAccuracy}])) by(node)`,
|
||||||
|
cpuCapacity: `sum(kube_node_status_allocatable{resource="cpu"}) by (node)`,
|
||||||
|
fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"}) by (node)`,
|
||||||
|
fsUsage: `sum(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) by (node)`
|
||||||
|
}
|
||||||
|
case 'pods':
|
||||||
|
return {
|
||||||
|
cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
|
||||||
|
cpuRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||||
|
cpuLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||||
|
memoryUsage: `sum(container_memory_working_set_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||||
|
memoryRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||||
|
memoryLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||||
|
fsUsage: `sum(container_fs_usage_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||||
|
networkReceive: `sum(rate(container_network_receive_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
|
||||||
|
networkTransmit: `sum(rate(container_network_transmit_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`
|
||||||
|
}
|
||||||
|
case 'pvc':
|
||||||
|
return {
|
||||||
|
diskUsage: `sum(kubelet_volume_stats_used_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`,
|
||||||
|
diskCapacity: `sum(kubelet_volume_stats_capacity_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`
|
||||||
|
}
|
||||||
|
case 'ingress':
|
||||||
|
const bytesSent = (ingress: string, statuses: string) =>
|
||||||
|
`sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`
|
||||||
|
return {
|
||||||
|
bytesSentSuccess: bytesSent(opts.igress, "^2\\\\d*"),
|
||||||
|
bytesSentFailure: bytesSent(opts.ingres, "^5\\\\d*"),
|
||||||
|
requestDurationSeconds: `sum(rate(nginx_ingress_controller_request_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`,
|
||||||
|
responseDurationSeconds: `sum(rate(nginx_ingress_controller_response_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -125,6 +125,8 @@ export class ShellSession extends EventEmitter {
|
|||||||
if (this.preferences.httpsProxy) {
|
if (this.preferences.httpsProxy) {
|
||||||
env["HTTPS_PROXY"] = this.preferences.httpsProxy
|
env["HTTPS_PROXY"] = this.preferences.httpsProxy
|
||||||
}
|
}
|
||||||
|
const no_proxy = ["localhost", "127.0.0.1", env["NO_PROXY"]]
|
||||||
|
env["NO_PROXY"] = no_proxy.filter(address => !!address).join()
|
||||||
if (env.DEBUG) { // do not pass debug option to bash
|
if (env.DEBUG) { // do not pass debug option to bash
|
||||||
delete env["DEBUG"]
|
delete env["DEBUG"]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import version260Beta3 from "./2.6.0-beta.3"
|
|||||||
import version270Beta0 from "./2.7.0-beta.0"
|
import version270Beta0 from "./2.7.0-beta.0"
|
||||||
import version270Beta1 from "./2.7.0-beta.1"
|
import version270Beta1 from "./2.7.0-beta.1"
|
||||||
import version360Beta1 from "./3.6.0-beta.1"
|
import version360Beta1 from "./3.6.0-beta.1"
|
||||||
|
import snap from "./snap"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
...version200Beta2,
|
...version200Beta2,
|
||||||
@ -16,4 +17,5 @@ export default {
|
|||||||
...version270Beta0,
|
...version270Beta0,
|
||||||
...version270Beta1,
|
...version270Beta1,
|
||||||
...version360Beta1,
|
...version360Beta1,
|
||||||
|
...snap
|
||||||
}
|
}
|
||||||
33
src/migrations/cluster-store/snap.ts
Normal file
33
src/migrations/cluster-store/snap.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Fix embedded kubeconfig paths under snap config
|
||||||
|
|
||||||
|
import { migration } from "../migration-wrapper";
|
||||||
|
import { ClusterModel, ClusterStore } from "../../common/cluster-store";
|
||||||
|
import { getAppVersion } from "../../common/utils/app-version";
|
||||||
|
import fs from "fs"
|
||||||
|
|
||||||
|
export default migration({
|
||||||
|
version: getAppVersion(), // Run always after upgrade
|
||||||
|
run(store, printLog) {
|
||||||
|
if (!process.env["SNAP"]) return;
|
||||||
|
|
||||||
|
printLog("Migrating embedded kubeconfig paths")
|
||||||
|
const storedClusters: ClusterModel[] = store.get("clusters") || [];
|
||||||
|
if (!storedClusters.length) return;
|
||||||
|
|
||||||
|
printLog("Number of clusters to migrate: ", storedClusters.length)
|
||||||
|
const migratedClusters = storedClusters
|
||||||
|
.map(cluster => {
|
||||||
|
/**
|
||||||
|
* replace snap version with 'current' in kubeconfig path
|
||||||
|
*/
|
||||||
|
if (!fs.existsSync(cluster.kubeConfigPath)) {
|
||||||
|
const kubeconfigPath = cluster.kubeConfigPath.replace(/\/snap\/kontena-lens\/[0-9]*\//, "/snap/kontena-lens/current/")
|
||||||
|
cluster.kubeConfigPath = kubeconfigPath
|
||||||
|
}
|
||||||
|
return cluster;
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
store.set("clusters", migratedClusters)
|
||||||
|
}
|
||||||
|
})
|
||||||
@ -223,6 +223,7 @@ export class Issuer extends KubeObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getConditions() {
|
getConditions() {
|
||||||
|
if (!this.status?.conditions) return [];
|
||||||
const { conditions = [] } = this.status;
|
const { conditions = [] } = this.status;
|
||||||
return conditions.map(condition => {
|
return conditions.map(condition => {
|
||||||
const { message, reason, lastTransitionTime, status } = condition;
|
const { message, reason, lastTransitionTime, status } = condition;
|
||||||
|
|||||||
@ -50,7 +50,7 @@ export class CustomResourceDefinition extends KubeObject {
|
|||||||
message: string;
|
message: string;
|
||||||
reason: string;
|
reason: string;
|
||||||
status: string;
|
status: string;
|
||||||
type: string;
|
type?: string;
|
||||||
}[];
|
}[];
|
||||||
acceptedNames: {
|
acceptedNames: {
|
||||||
plural: string;
|
plural: string;
|
||||||
@ -132,7 +132,7 @@ export class CustomResourceDefinition extends KubeObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getConditions() {
|
getConditions() {
|
||||||
if (!this.status.conditions) return [];
|
if (!this.status?.conditions) return [];
|
||||||
return this.status.conditions.map(condition => {
|
return this.status.conditions.map(condition => {
|
||||||
const { message, reason, lastTransitionTime, status } = condition;
|
const { message, reason, lastTransitionTime, status } = condition;
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -115,12 +115,12 @@ export class KubeObject implements ItemObject {
|
|||||||
return KubeObject.stringifyLabels(this.metadata.labels);
|
return KubeObject.stringifyLabels(this.metadata.labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
getAnnotations(): string[] {
|
getAnnotations(filter = false): string[] {
|
||||||
const labels = KubeObject.stringifyLabels(this.metadata.annotations);
|
const labels = KubeObject.stringifyLabels(this.metadata.annotations);
|
||||||
return labels.filter(label => {
|
return filter ? labels.filter(label => {
|
||||||
const skip = resourceApplierApi.annotations.some(key => label.startsWith(key));
|
const skip = resourceApplierApi.annotations.some(key => label.startsWith(key));
|
||||||
return !skip;
|
return !skip;
|
||||||
})
|
}) : labels;
|
||||||
}
|
}
|
||||||
|
|
||||||
getOwnerRefs() {
|
getOwnerRefs() {
|
||||||
@ -138,7 +138,7 @@ export class KubeObject implements ItemObject {
|
|||||||
getNs(),
|
getNs(),
|
||||||
getId(),
|
getId(),
|
||||||
...getLabels(),
|
...getLabels(),
|
||||||
...getAnnotations(),
|
...getAnnotations(true),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import "./components/app.scss"
|
import "./components/app.scss"
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { render } from "react-dom";
|
import { render, unmountComponentAtNode } from "react-dom";
|
||||||
import { isMac } from "../common/vars";
|
import { isMac } from "../common/vars";
|
||||||
import { userStore } from "../common/user-store";
|
import { userStore } from "../common/user-store";
|
||||||
import { workspaceStore } from "../common/workspace-store";
|
import { workspaceStore } from "../common/workspace-store";
|
||||||
@ -30,12 +30,27 @@ export async function bootstrap(App: AppComponent) {
|
|||||||
themeStore.init(),
|
themeStore.init(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Register additional store listeners
|
||||||
|
clusterStore.registerIpcListener();
|
||||||
|
|
||||||
// init app's dependencies if any
|
// init app's dependencies if any
|
||||||
if (App.init) {
|
if (App.init) {
|
||||||
await App.init();
|
await App.init();
|
||||||
extensionStore.autoEnableOnLoad(getLensRuntime);
|
extensionStore.autoEnableOnLoad(getLensRuntime);
|
||||||
}
|
}
|
||||||
render(<App/>, rootElem);
|
window.addEventListener("message", (ev: MessageEvent) => {
|
||||||
|
if (ev.data === "teardown") {
|
||||||
|
userStore.unregisterIpcListener()
|
||||||
|
workspaceStore.unregisterIpcListener()
|
||||||
|
clusterStore.unregisterIpcListener()
|
||||||
|
unmountComponentAtNode(rootElem)
|
||||||
|
window.location.href = "about:blank"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
render(<>
|
||||||
|
{isMac && <div id="draggable-top" />}
|
||||||
|
<App />
|
||||||
|
</>, rootElem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// run
|
// run
|
||||||
|
|||||||
@ -99,10 +99,7 @@ export class AddCluster extends React.Component {
|
|||||||
getContexts(config: KubeConfig): Map<string, KubeConfig> {
|
getContexts(config: KubeConfig): Map<string, KubeConfig> {
|
||||||
const contexts = new Map();
|
const contexts = new Map();
|
||||||
splitConfig(config).forEach(config => {
|
splitConfig(config).forEach(config => {
|
||||||
const isExists = clusterStore.hasContext(config.currentContext);
|
|
||||||
if (!isExists) {
|
|
||||||
contexts.set(config.currentContext, config);
|
contexts.set(config.currentContext, config);
|
||||||
}
|
|
||||||
})
|
})
|
||||||
return contexts
|
return contexts
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,8 +3,8 @@ import "./helm-chart-details.scss";
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { HelmChart, helmChartsApi } from "../../api/endpoints/helm-charts.api";
|
import { HelmChart, helmChartsApi } from "../../api/endpoints/helm-charts.api";
|
||||||
import { t, Trans } from "@lingui/macro";
|
import { t, Trans } from "@lingui/macro";
|
||||||
import { autorun, observable } from "mobx";
|
import { observable, toJS } from "mobx";
|
||||||
import { disposeOnUnmount, observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { Drawer, DrawerItem } from "../drawer";
|
import { Drawer, DrawerItem } from "../drawer";
|
||||||
import { autobind, stopPropagation } from "../../utils";
|
import { autobind, stopPropagation } from "../../utils";
|
||||||
import { MarkdownViewer } from "../markdown-viewer";
|
import { MarkdownViewer } from "../markdown-viewer";
|
||||||
@ -25,39 +25,41 @@ interface Props {
|
|||||||
export class HelmChartDetails extends Component<Props> {
|
export class HelmChartDetails extends Component<Props> {
|
||||||
@observable chartVersions: HelmChart[];
|
@observable chartVersions: HelmChart[];
|
||||||
@observable selectedChart: HelmChart;
|
@observable selectedChart: HelmChart;
|
||||||
@observable description: string = null;
|
@observable readme: string = null;
|
||||||
|
@observable error: string = null;
|
||||||
|
|
||||||
private chartPromise: CancelablePromise<{ readme: string; versions: HelmChart[] }>;
|
private chartPromise: CancelablePromise<{ readme: string; versions: HelmChart[] }>;
|
||||||
|
|
||||||
@disposeOnUnmount
|
async componentDidMount() {
|
||||||
chartSelector = autorun(async () => {
|
const { chart: { name, repo, version } } = this.props
|
||||||
if (!this.props.chart) return;
|
|
||||||
this.chartVersions = null;
|
|
||||||
this.selectedChart = null;
|
|
||||||
this.description = null;
|
|
||||||
this.loadChartData();
|
|
||||||
this.chartPromise.then(data => {
|
|
||||||
this.description = data.readme;
|
|
||||||
this.chartVersions = data.versions;
|
|
||||||
this.selectedChart = data.versions[0];
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
loadChartData(version?: string) {
|
try {
|
||||||
const { chart: { name, repo } } = this.props;
|
const { readme, versions } = await (this.chartPromise = helmChartsApi.get(repo, name, version))
|
||||||
if (this.chartPromise) this.chartPromise.cancel();
|
this.readme = readme
|
||||||
this.chartPromise = helmChartsApi.get(repo, name, version);
|
this.chartVersions = versions
|
||||||
|
this.selectedChart = versions[0]
|
||||||
|
} catch (error) {
|
||||||
|
this.error = error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.chartPromise?.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@autobind()
|
@autobind()
|
||||||
onVersionChange(opt: SelectOption) {
|
async onVersionChange({ value: version }: SelectOption) {
|
||||||
const version = opt.value;
|
|
||||||
this.selectedChart = this.chartVersions.find(chart => chart.version === version);
|
this.selectedChart = this.chartVersions.find(chart => chart.version === version);
|
||||||
this.description = null;
|
this.readme = null;
|
||||||
this.loadChartData(version);
|
|
||||||
this.chartPromise.then(data => {
|
try {
|
||||||
this.description = data.readme
|
this.chartPromise?.cancel();
|
||||||
});
|
const { chart: { name, repo } } = this.props;
|
||||||
|
const { readme } = await (this.chartPromise = helmChartsApi.get(repo, name, version))
|
||||||
|
this.readme = readme;
|
||||||
|
} catch (error) {
|
||||||
|
this.error = error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@autobind()
|
@autobind()
|
||||||
@ -79,7 +81,7 @@ export class HelmChartDetails extends Component<Props> {
|
|||||||
<div className="intro-contents box grow">
|
<div className="intro-contents box grow">
|
||||||
<div className="description flex align-center justify-space-between">
|
<div className="description flex align-center justify-space-between">
|
||||||
{selectedChart.getDescription()}
|
{selectedChart.getDescription()}
|
||||||
<Button primary label={_i18n._(t`Install`)} onClick={this.install}/>
|
<Button primary label={_i18n._(t`Install`)} onClick={this.install} />
|
||||||
</div>
|
</div>
|
||||||
<DrawerItem name={_i18n._(t`Version`)} className="version" onClick={stopPropagation}>
|
<DrawerItem name={_i18n._(t`Version`)} className="version" onClick={stopPropagation}>
|
||||||
<Select
|
<Select
|
||||||
@ -95,12 +97,12 @@ export class HelmChartDetails extends Component<Props> {
|
|||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
<DrawerItem name={_i18n._(t`Maintainers`)} className="maintainers">
|
<DrawerItem name={_i18n._(t`Maintainers`)} className="maintainers">
|
||||||
{selectedChart.getMaintainers().map(({ name, email, url }) =>
|
{selectedChart.getMaintainers().map(({ name, email, url }) =>
|
||||||
<a key={name} href={url ? url : `mailto:${email}`} target="_blank">{name}</a>
|
<a key={name} href={url || `mailto:${email}`} target="_blank">{name}</a>
|
||||||
)}
|
)}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
{selectedChart.getKeywords().length > 0 && (
|
{selectedChart.getKeywords().length > 0 && (
|
||||||
<DrawerItem name={_i18n._(t`Keywords`)} labelsOnly>
|
<DrawerItem name={_i18n._(t`Keywords`)} labelsOnly>
|
||||||
{selectedChart.getKeywords().map(key => <Badge key={key} label={key}/>)}
|
{selectedChart.getKeywords().map(key => <Badge key={key} label={key} />)}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -108,14 +110,35 @@ export class HelmChartDetails extends Component<Props> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderReadme() {
|
||||||
|
if (this.readme === null) {
|
||||||
|
return <Spinner center />
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="chart-description">
|
||||||
|
<MarkdownViewer markdown={this.readme} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
renderContent() {
|
renderContent() {
|
||||||
if (this.selectedChart === null || this.description === null) return <Spinner center/>;
|
if (!this.selectedChart) {
|
||||||
|
return <Spinner center />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.error) {
|
||||||
|
return (
|
||||||
|
<div className="box grow">
|
||||||
|
<p className="error">{this.error}</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="box grow">
|
<div className="box grow">
|
||||||
{this.renderIntroduction()}
|
{this.renderIntroduction()}
|
||||||
<div className="chart-description">
|
{this.renderReadme()}
|
||||||
<MarkdownViewer markdown={this.description}/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -72,7 +72,7 @@ export class HelmCharts extends Component<Props> {
|
|||||||
(items: HelmChart[]) => items.filter(item => !item.deprecated)
|
(items: HelmChart[]) => items.filter(item => !item.deprecated)
|
||||||
]}
|
]}
|
||||||
customizeHeader={() => (
|
customizeHeader={() => (
|
||||||
<SearchInput placeholder={_i18n._(t`Search Helm Charts`)}/>
|
<SearchInput placeholder={_i18n._(t`Search Helm Charts`)} />
|
||||||
)}
|
)}
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ className: "icon" },
|
{ className: "icon" },
|
||||||
@ -99,10 +99,12 @@ export class HelmCharts extends Component<Props> {
|
|||||||
detailsItem={this.selectedChart}
|
detailsItem={this.selectedChart}
|
||||||
onDetails={this.showDetails}
|
onDetails={this.showDetails}
|
||||||
/>
|
/>
|
||||||
|
{this.selectedChart && (
|
||||||
<HelmChartDetails
|
<HelmChartDetails
|
||||||
chart={this.selectedChart}
|
chart={this.selectedChart}
|
||||||
hideDetails={this.hideDetails}
|
hideDetails={this.hideDetails}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,8 +13,9 @@ import { apiManager } from "../../api/api-manager";
|
|||||||
import { crdStore } from "./crd.store";
|
import { crdStore } from "./crd.store";
|
||||||
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
||||||
import { Input } from "../input";
|
import { Input } from "../input";
|
||||||
|
import { CustomResourceDefinition } from "../../api/endpoints/crd.api";
|
||||||
|
|
||||||
interface Props extends KubeObjectDetailsProps {
|
interface Props extends KubeObjectDetailsProps<CustomResourceDefinition> {
|
||||||
}
|
}
|
||||||
|
|
||||||
function CrdColumnValue({ value }: { value: any[] | {} | string }) {
|
function CrdColumnValue({ value }: { value: any[] | {} | string }) {
|
||||||
@ -66,12 +67,14 @@ export class CrdResourceDetails extends React.Component<Props> {
|
|||||||
})}
|
})}
|
||||||
{showStatus && (
|
{showStatus && (
|
||||||
<DrawerItem name={<Trans>Status</Trans>} className="status" labelsOnly>
|
<DrawerItem name={<Trans>Status</Trans>} className="status" labelsOnly>
|
||||||
{object.status.conditions.map((condition: { type: string; message: string; status: string }) => {
|
{object.status.conditions.map((condition, index) => {
|
||||||
const { type, message, status } = condition;
|
const { type, reason, message, status } = condition;
|
||||||
|
const kind = type || reason;
|
||||||
|
if (!kind) return null;
|
||||||
return (
|
return (
|
||||||
<Badge
|
<Badge
|
||||||
key={type} label={type}
|
key={kind + index} label={kind}
|
||||||
className={cssNames({ disabled: status === "False" }, type.toLowerCase())}
|
className={cssNames({ disabled: status === "False" }, kind.toLowerCase())}
|
||||||
tooltip={message}
|
tooltip={message}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -58,7 +58,7 @@ export class NamespaceSelect extends React.Component<Props> {
|
|||||||
const { value, label } = option;
|
const { value, label } = option;
|
||||||
return label || (
|
return label || (
|
||||||
<>
|
<>
|
||||||
{showIcons && <Icon small material="layers"/>}
|
{showIcons && <Icon small material="layers" />}
|
||||||
{value}
|
{value}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@ -91,14 +91,15 @@ export class NamespaceSelectFilter extends React.Component {
|
|||||||
closeMenuOnSelect={false}
|
closeMenuOnSelect={false}
|
||||||
isOptionSelected={() => false}
|
isOptionSelected={() => false}
|
||||||
controlShouldRenderValue={false}
|
controlShouldRenderValue={false}
|
||||||
onChange={({ value: namespace }: SelectOption) => toggleContext(namespace)}
|
isMulti
|
||||||
|
onChange={([{ value }]: SelectOption[]) => toggleContext(value)}
|
||||||
formatOptionLabel={({ value: namespace }: SelectOption) => {
|
formatOptionLabel={({ value: namespace }: SelectOption) => {
|
||||||
const isSelected = hasContext(namespace);
|
const isSelected = hasContext(namespace);
|
||||||
return (
|
return (
|
||||||
<div className="flex gaps align-center">
|
<div className="flex gaps align-center">
|
||||||
<FilterIcon type={FilterType.NAMESPACE}/>
|
<FilterIcon type={FilterType.NAMESPACE} />
|
||||||
<span>{namespace}</span>
|
<span>{namespace}</span>
|
||||||
{isSelected && <Icon small material="check" className="box right"/>}
|
{isSelected && <Icon small material="check" className="box right" />}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -18,44 +18,22 @@ export const KubectlBinaries = observer(({ preferences }: { preferences: UserPre
|
|||||||
{ value: "china", label: "China (Azure)" },
|
{ value: "china", label: "China (Azure)" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
const save = () => {
|
const save = () => {
|
||||||
preferences.downloadBinariesPath = downloadPath;
|
preferences.downloadBinariesPath = downloadPath;
|
||||||
preferences.kubectlBinariesPath = binariesPath;
|
preferences.kubectlBinariesPath = binariesPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderPath = () => {
|
|
||||||
if (preferences.downloadKubectlBinaries) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<SubTitle title="Path to Kubectl binary"/>
|
|
||||||
<Input
|
|
||||||
theme="round-black"
|
|
||||||
value={binariesPath}
|
|
||||||
validators={isPath}
|
|
||||||
onChange={setBinariesPath}
|
|
||||||
onBlur={save}
|
|
||||||
/>
|
|
||||||
<small className="hint">
|
|
||||||
<Trans>Default:</Trans>{" "}{Kubectl.bundledKubectlPath}
|
|
||||||
</small>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h2><Trans>Kubectl Binary</Trans></h2>
|
<h2><Trans>Kubectl Binary</Trans></h2>
|
||||||
<small className="hint">
|
|
||||||
<Trans>Download kubectl binaries matching to Kubernetes cluster verison.</Trans>
|
|
||||||
</small>
|
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label={<Trans>Download kubectl binaries</Trans>}
|
label={<Trans>Download kubectl binaries</Trans>}
|
||||||
value={preferences.downloadKubectlBinaries}
|
value={preferences.downloadKubectlBinaries}
|
||||||
onChange={downloadKubectlBinaries => preferences.downloadKubectlBinaries = downloadKubectlBinaries}
|
onChange={downloadKubectlBinaries => preferences.downloadKubectlBinaries = downloadKubectlBinaries}
|
||||||
/>
|
/>
|
||||||
|
<small className="hint">
|
||||||
|
<Trans>Download kubectl binaries matching to Kubernetes cluster version.</Trans>
|
||||||
|
</small>
|
||||||
<SubTitle title="Download mirror" />
|
<SubTitle title="Download mirror" />
|
||||||
<Select
|
<Select
|
||||||
placeholder={<Trans>Download mirror for kubectl</Trans>}
|
placeholder={<Trans>Download mirror for kubectl</Trans>}
|
||||||
@ -64,20 +42,32 @@ export const KubectlBinaries = observer(({ preferences }: { preferences: UserPre
|
|||||||
onChange={({ value }: SelectOption) => preferences.downloadMirror = value}
|
onChange={({ value }: SelectOption) => preferences.downloadMirror = value}
|
||||||
disabled={!preferences.downloadKubectlBinaries}
|
disabled={!preferences.downloadKubectlBinaries}
|
||||||
/>
|
/>
|
||||||
<SubTitle title="Directory for binaries"/>
|
<SubTitle title="Directory for binaries" />
|
||||||
<Input
|
<Input
|
||||||
theme="round-black"
|
theme="round-black"
|
||||||
value={downloadPath}
|
value={downloadPath}
|
||||||
placeholder={`Directory to download binaries into`}
|
placeholder={userStore.getDefaultKubectlPath()}
|
||||||
validators={isPath}
|
validators={isPath}
|
||||||
onChange={setDownloadPath}
|
onChange={setDownloadPath}
|
||||||
onBlur={save}
|
onBlur={save}
|
||||||
disabled={!preferences.downloadKubectlBinaries}
|
disabled={!preferences.downloadKubectlBinaries}
|
||||||
/>
|
/>
|
||||||
<small>
|
<small className="hint">
|
||||||
Default: {userStore.getDefaultKubectlPath()}
|
The directory to download binaries into.
|
||||||
|
</small>
|
||||||
|
<SubTitle title="Path to Kubectl binary" />
|
||||||
|
<Input
|
||||||
|
theme="round-black"
|
||||||
|
placeholder={Kubectl.bundledKubectlPath}
|
||||||
|
value={binariesPath}
|
||||||
|
validators={isPath}
|
||||||
|
onChange={setBinariesPath}
|
||||||
|
onBlur={save}
|
||||||
|
disabled={preferences.downloadKubectlBinaries}
|
||||||
|
/>
|
||||||
|
<small className="hint">
|
||||||
|
<Trans>The path to the kubectl binary on the system.</Trans>
|
||||||
</small>
|
</small>
|
||||||
{renderPath()}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -11,11 +11,9 @@ export class DaemonSetStore extends KubeObjectStore<DaemonSet> {
|
|||||||
|
|
||||||
@observable metrics: IPodMetrics = null;
|
@observable metrics: IPodMetrics = null;
|
||||||
|
|
||||||
loadMetrics(daemonSet: DaemonSet) {
|
async loadMetrics(daemonSet: DaemonSet) {
|
||||||
const pods = this.getChildPods(daemonSet);
|
const pods = this.getChildPods(daemonSet);
|
||||||
return podsApi.getMetrics(pods, daemonSet.getNs(), "").then(metrics =>
|
this.metrics = await podsApi.getMetrics(pods, daemonSet.getNs(), "");
|
||||||
this.metrics = metrics
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getChildPods(daemonSet: DaemonSet): Pod[] {
|
getChildPods(daemonSet: DaemonSet): Pod[] {
|
||||||
|
|||||||
@ -16,11 +16,9 @@ export class DeploymentStore extends KubeObjectStore<Deployment> {
|
|||||||
], "desc");
|
], "desc");
|
||||||
}
|
}
|
||||||
|
|
||||||
loadMetrics(deployment: Deployment) {
|
async loadMetrics(deployment: Deployment) {
|
||||||
const pods = this.getChildPods(deployment);
|
const pods = this.getChildPods(deployment);
|
||||||
return podsApi.getMetrics(pods, deployment.getNs(), "").then(metrics =>
|
this.metrics = await podsApi.getMetrics(pods, deployment.getNs(), "");
|
||||||
this.metrics = metrics
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getStatuses(deployments?: Deployment[]) {
|
getStatuses(deployments?: Deployment[]) {
|
||||||
|
|||||||
@ -5,72 +5,54 @@ import { observer } from "mobx-react";
|
|||||||
import { Trans } from "@lingui/macro";
|
import { Trans } from "@lingui/macro";
|
||||||
import { OverviewWorkloadStatus } from "./overview-workload-status";
|
import { OverviewWorkloadStatus } from "./overview-workload-status";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { cronJobsURL, daemonSetsURL, deploymentsURL, jobsURL, podsURL, statefulSetsURL } from "../+workloads";
|
import { workloadURL, workloadStores } from "../+workloads";
|
||||||
import { podsStore } from "../+workloads-pods/pods.store";
|
|
||||||
import { deploymentStore } from "../+workloads-deployments/deployments.store";
|
|
||||||
import { daemonSetStore } from "../+workloads-daemonsets/daemonsets.store";
|
|
||||||
import { statefulSetStore } from "../+workloads-statefulsets/statefulset.store";
|
|
||||||
import { jobStore } from "../+workloads-jobs/job.store";
|
|
||||||
import { cronJobStore } from "../+workloads-cronjobs/cronjob.store";
|
|
||||||
import { namespaceStore } from "../+namespaces/namespace.store";
|
import { namespaceStore } from "../+namespaces/namespace.store";
|
||||||
import { PageFiltersList } from "../item-object-list/page-filters-list";
|
import { PageFiltersList } from "../item-object-list/page-filters-list";
|
||||||
import { NamespaceSelectFilter } from "../+namespaces/namespace-select";
|
import { NamespaceSelectFilter } from "../+namespaces/namespace-select";
|
||||||
import { isAllowedResource } from "../../../common/rbac";
|
import { isAllowedResource, KubeResource } from "../../../common/rbac";
|
||||||
|
import { ResourceNames } from "../../../renderer/utils/rbac";
|
||||||
|
import { autobind } from "../../utils";
|
||||||
|
import { _i18n } from "../../i18n";
|
||||||
|
|
||||||
|
const resources: KubeResource[] = [
|
||||||
|
"pods",
|
||||||
|
"deployments",
|
||||||
|
"statefulsets",
|
||||||
|
"daemonsets",
|
||||||
|
"jobs",
|
||||||
|
"cronjobs",
|
||||||
|
]
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class OverviewStatuses extends React.Component {
|
export class OverviewStatuses extends React.Component {
|
||||||
|
@autobind()
|
||||||
|
renderWorkload(resource: KubeResource): React.ReactElement {
|
||||||
|
const store = workloadStores[resource];
|
||||||
|
const items = store.getAllByNs(namespaceStore.contextNs)
|
||||||
|
return (
|
||||||
|
<div className="workload" key={resource}>
|
||||||
|
<div className="title">
|
||||||
|
<Link to={workloadURL[resource]()}>{ResourceNames[resource]} ({items.length})</Link>
|
||||||
|
</div>
|
||||||
|
<OverviewWorkloadStatus status={store.getStatuses(items)} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { contextNs } = namespaceStore;
|
const workloads = resources
|
||||||
const pods = isAllowedResource("pods") ? podsStore.getAllByNs(contextNs) : [];
|
.filter(isAllowedResource)
|
||||||
const deployments = isAllowedResource("deployments") ? deploymentStore.getAllByNs(contextNs) : [];
|
.map(this.renderWorkload);
|
||||||
const statefulSets = isAllowedResource("statefulsets") ? statefulSetStore.getAllByNs(contextNs) : [];
|
|
||||||
const daemonSets = isAllowedResource("daemonsets") ? daemonSetStore.getAllByNs(contextNs) : [];
|
|
||||||
const jobs = isAllowedResource("jobs") ? jobStore.getAllByNs(contextNs) : [];
|
|
||||||
const cronJobs = isAllowedResource("cronjobs") ? cronJobStore.getAllByNs(contextNs) : [];
|
|
||||||
return (
|
return (
|
||||||
<div className="OverviewStatuses">
|
<div className="OverviewStatuses">
|
||||||
<div className="header flex gaps align-center">
|
<div className="header flex gaps align-center">
|
||||||
<h5 className="box grow"><Trans>Overview</Trans></h5>
|
<h5 className="box grow"><Trans>Overview</Trans></h5>
|
||||||
<NamespaceSelectFilter/>
|
<NamespaceSelectFilter />
|
||||||
</div>
|
</div>
|
||||||
<PageFiltersList/>
|
<PageFiltersList />
|
||||||
<div className="workloads">
|
<div className="workloads">
|
||||||
{isAllowedResource("pods") &&
|
{workloads}
|
||||||
<div className="workload">
|
|
||||||
<div className="title"><Link to={podsURL()}><Trans>Pods</Trans> ({pods.length})</Link></div>
|
|
||||||
<OverviewWorkloadStatus status={podsStore.getStatuses(pods)}/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{isAllowedResource("deployments") &&
|
|
||||||
<div className="workload">
|
|
||||||
<div className="title"><Link to={deploymentsURL()}><Trans>Deployments</Trans> ({deployments.length})</Link></div>
|
|
||||||
<OverviewWorkloadStatus status={deploymentStore.getStatuses(deployments)}/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{isAllowedResource("statefulsets") &&
|
|
||||||
<div className="workload">
|
|
||||||
<div className="title"><Link to={statefulSetsURL()}><Trans>StatefulSets</Trans> ({statefulSets.length})</Link></div>
|
|
||||||
<OverviewWorkloadStatus status={statefulSetStore.getStatuses(statefulSets)}/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{isAllowedResource("daemonsets") &&
|
|
||||||
<div className="workload">
|
|
||||||
<div className="title"><Link to={daemonSetsURL()}><Trans>DaemonSets</Trans> ({daemonSets.length})</Link></div>
|
|
||||||
<OverviewWorkloadStatus status={daemonSetStore.getStatuses(daemonSets)}/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{isAllowedResource("jobs") &&
|
|
||||||
<div className="workload">
|
|
||||||
<div className="title"><Link to={jobsURL()}><Trans>Jobs</Trans> ({jobs.length})</Link></div>
|
|
||||||
<OverviewWorkloadStatus status={jobStore.getStatuses(jobs)}/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{isAllowedResource("cronjobs") &&
|
|
||||||
<div className="workload">
|
|
||||||
<div className="title"><Link to={cronJobsURL()}><Trans>CronJobs</Trans> ({cronJobs.length})</Link></div>
|
|
||||||
<OverviewWorkloadStatus status={cronJobStore.getStatuses(cronJobs)}/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -113,7 +113,8 @@ const SecretKey = (props: SecretKeyProps) => {
|
|||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [secret, setSecret] = useState<Secret>()
|
const [secret, setSecret] = useState<Secret>()
|
||||||
|
|
||||||
const showKey = async () => {
|
const showKey = async (evt: React.MouseEvent) => {
|
||||||
|
evt.preventDefault()
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
const secret = await secretsStore.load({ name, namespace });
|
const secret = await secretsStore.load({ name, namespace });
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
|||||||
@ -10,11 +10,9 @@ export class ReplicaSetStore extends KubeObjectStore<ReplicaSet> {
|
|||||||
api = replicaSetApi
|
api = replicaSetApi
|
||||||
@observable metrics: IPodMetrics = null;
|
@observable metrics: IPodMetrics = null;
|
||||||
|
|
||||||
loadMetrics(replicaSet: ReplicaSet) {
|
async loadMetrics(replicaSet: ReplicaSet) {
|
||||||
const pods = this.getChildPods(replicaSet);
|
const pods = this.getChildPods(replicaSet);
|
||||||
return podsApi.getMetrics(pods, replicaSet.getNs(), "").then(metrics =>
|
this.metrics = await podsApi.getMetrics(pods, replicaSet.getNs(), "");
|
||||||
this.metrics = metrics
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getChildPods(replicaSet: ReplicaSet) {
|
getChildPods(replicaSet: ReplicaSet) {
|
||||||
|
|||||||
@ -10,11 +10,9 @@ export class StatefulSetStore extends KubeObjectStore<StatefulSet> {
|
|||||||
api = statefulSetApi
|
api = statefulSetApi
|
||||||
@observable metrics: IPodMetrics = null;
|
@observable metrics: IPodMetrics = null;
|
||||||
|
|
||||||
loadMetrics(statefulSet: StatefulSet) {
|
async loadMetrics(statefulSet: StatefulSet) {
|
||||||
const pods = this.getChildPods(statefulSet);
|
const pods = this.getChildPods(statefulSet);
|
||||||
return podsApi.getMetrics(pods, statefulSet.getNs(), "").then(metrics =>
|
this.metrics = await podsApi.getMetrics(pods, statefulSet.getNs(), "");
|
||||||
this.metrics = metrics
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getChildPods(statefulSet: StatefulSet) {
|
getChildPods(statefulSet: StatefulSet) {
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
export * from "./workloads.route"
|
export * from "./workloads.route"
|
||||||
export * from "./workloads"
|
export * from "./workloads"
|
||||||
|
export * from "./workloads.stores"
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { RouteProps } from "react-router"
|
import { RouteProps } from "react-router"
|
||||||
import { Workloads } from "./workloads";
|
import { Workloads } from "./workloads";
|
||||||
import { buildURL, IURLParams } from "../../navigation";
|
import { buildURL, IURLParams } from "../../navigation";
|
||||||
|
import { KubeResource } from "../../../common/rbac";
|
||||||
|
|
||||||
export const workloadsRoute: RouteProps = {
|
export const workloadsRoute: RouteProps = {
|
||||||
get path() {
|
get path() {
|
||||||
@ -62,3 +63,12 @@ export const daemonSetsURL = buildURL<IDaemonSetsRouteParams>(daemonSetsRoute.pa
|
|||||||
export const statefulSetsURL = buildURL<IStatefulSetsRouteParams>(statefulSetsRoute.path)
|
export const statefulSetsURL = buildURL<IStatefulSetsRouteParams>(statefulSetsRoute.path)
|
||||||
export const jobsURL = buildURL<IJobsRouteParams>(jobsRoute.path)
|
export const jobsURL = buildURL<IJobsRouteParams>(jobsRoute.path)
|
||||||
export const cronJobsURL = buildURL<ICronJobsRouteParams>(cronJobsRoute.path)
|
export const cronJobsURL = buildURL<ICronJobsRouteParams>(cronJobsRoute.path)
|
||||||
|
|
||||||
|
export const workloadURL: Partial<Record<KubeResource, ReturnType<typeof buildURL>>> = {
|
||||||
|
"pods": podsURL,
|
||||||
|
"deployments": deploymentsURL,
|
||||||
|
"daemonsets": daemonSetsURL,
|
||||||
|
"statefulsets": statefulSetsURL,
|
||||||
|
"jobs": jobsURL,
|
||||||
|
"cronjobs": cronJobsURL,
|
||||||
|
}
|
||||||
|
|||||||
17
src/renderer/components/+workloads/workloads.stores.ts
Normal file
17
src/renderer/components/+workloads/workloads.stores.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { KubeObjectStore } from "../../kube-object.store";
|
||||||
|
import { podsStore } from "../+workloads-pods/pods.store";
|
||||||
|
import { deploymentStore } from "../+workloads-deployments/deployments.store";
|
||||||
|
import { daemonSetStore } from "../+workloads-daemonsets/daemonsets.store";
|
||||||
|
import { statefulSetStore } from "../+workloads-statefulsets/statefulset.store";
|
||||||
|
import { jobStore } from "../+workloads-jobs/job.store";
|
||||||
|
import { cronJobStore } from "../+workloads-cronjobs/cronjob.store";
|
||||||
|
import { KubeResource } from "../../../common/rbac";
|
||||||
|
|
||||||
|
export const workloadStores: Partial<Record<KubeResource, KubeObjectStore>> = {
|
||||||
|
"pods": podsStore,
|
||||||
|
"deployments": deploymentStore,
|
||||||
|
"daemonsets": daemonSetStore,
|
||||||
|
"statefulsets": statefulSetStore,
|
||||||
|
"jobs": jobStore,
|
||||||
|
"cronjobs": cronJobStore,
|
||||||
|
}
|
||||||
@ -13,6 +13,7 @@
|
|||||||
:root {
|
:root {
|
||||||
--mainBackground: #1e2124;
|
--mainBackground: #1e2124;
|
||||||
--main-layout-header: 40px;
|
--main-layout-header: 40px;
|
||||||
|
--drag-region-height: 22px
|
||||||
}
|
}
|
||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
@ -47,7 +48,7 @@ html, body {
|
|||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: var(--main-layout-header);
|
height: var(--drag-region-height);
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -165,7 +165,7 @@ export const memoryOptions: ChartOptions = {
|
|||||||
}
|
}
|
||||||
return bytesToUnits(parseInt(value));
|
return bytesToUnits(parseInt(value));
|
||||||
}
|
}
|
||||||
return `${value}`;
|
return bytesToUnits(value);
|
||||||
},
|
},
|
||||||
stepSize: 1
|
stepSize: 1
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,25 +55,24 @@ export class ClusterManager extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="ClusterManager">
|
<div className="ClusterManager">
|
||||||
<div id="draggable-top"/>
|
|
||||||
<main>
|
<main>
|
||||||
<div id="lens-views"/>
|
<div id="lens-views" />
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route component={LandingPage} {...landingRoute}/>
|
<Route component={LandingPage} {...landingRoute} />
|
||||||
<Route component={Preferences} {...preferencesRoute}/>
|
<Route component={Preferences} {...preferencesRoute} />
|
||||||
<Route component={Workspaces} {...workspacesRoute}/>
|
<Route component={Workspaces} {...workspacesRoute} />
|
||||||
<Route component={AddCluster} {...addClusterRoute}/>
|
<Route component={AddCluster} {...addClusterRoute} />
|
||||||
<Route component={ClusterView} {...clusterViewRoute}/>
|
<Route component={ClusterView} {...clusterViewRoute} />
|
||||||
<Route component={ClusterSettings} {...clusterSettingsRoute}/>
|
<Route component={ClusterSettings} {...clusterSettingsRoute} />
|
||||||
<Route component={Extensions} {...extensionsRoute}/>
|
<Route component={Extensions} {...extensionsRoute}/>
|
||||||
{dynamicPages.globalPages.map(({ path, components: { Page } }) => {
|
{dynamicPages.globalPages.map(({ path, components: { Page } }) => {
|
||||||
return <Route key={path} path={path} component={Page}/>
|
return <Route key={path} path={path} component={Page}/>
|
||||||
})}
|
})}
|
||||||
<Redirect exact to={this.startUrl}/>
|
<Redirect exact to={this.startUrl} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</main>
|
</main>
|
||||||
<ClustersMenu/>
|
<ClustersMenu />
|
||||||
<BottomBar/>
|
<BottomBar />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,8 +19,11 @@ export async function initView(clusterId: ClusterId) {
|
|||||||
if (!clusterId || lensViews.has(clusterId)) {
|
if (!clusterId || lensViews.has(clusterId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logger.info(`[LENS-VIEW]: init dashboard, clusterId=${clusterId}`)
|
|
||||||
const cluster = clusterStore.getById(clusterId);
|
const cluster = clusterStore.getById(clusterId);
|
||||||
|
if (!cluster) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.info(`[LENS-VIEW]: init dashboard, clusterId=${clusterId}`)
|
||||||
const parentElem = document.getElementById("lens-views");
|
const parentElem = document.getElementById("lens-views");
|
||||||
const iframe = document.createElement("iframe");
|
const iframe = document.createElement("iframe");
|
||||||
iframe.name = cluster.contextName;
|
iframe.name = cluster.contextName;
|
||||||
@ -42,9 +45,9 @@ export async function autoCleanOnRemove(clusterId: ClusterId, iframe: HTMLIFrame
|
|||||||
// Keep frame in DOM to avoid possible bugs when same cluster re-created after being removed.
|
// Keep frame in DOM to avoid possible bugs when same cluster re-created after being removed.
|
||||||
// In that case for some reasons `webFrame.routingId` returns some previous frameId (usage in app.tsx)
|
// In that case for some reasons `webFrame.routingId` returns some previous frameId (usage in app.tsx)
|
||||||
// Issue: https://github.com/lensapp/lens/issues/811
|
// Issue: https://github.com/lensapp/lens/issues/811
|
||||||
iframe.dataset.meta = `${iframe.name} was removed at ${new Date().toLocaleString()}`;
|
iframe.dataset.meta = `${iframe.name} was removed at ${new Date().toLocaleString()}`
|
||||||
iframe.removeAttribute("src")
|
|
||||||
iframe.removeAttribute("name")
|
iframe.removeAttribute("name")
|
||||||
|
iframe.contentWindow.postMessage("teardown", "*")
|
||||||
}
|
}
|
||||||
|
|
||||||
export function refreshViews() {
|
export function refreshViews() {
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { t } from "@lingui/macro";
|
|||||||
import { HelmChart, helmChartsApi } from "../../api/endpoints/helm-charts.api";
|
import { HelmChart, helmChartsApi } from "../../api/endpoints/helm-charts.api";
|
||||||
import { IReleaseUpdateDetails } from "../../api/endpoints/helm-releases.api";
|
import { IReleaseUpdateDetails } from "../../api/endpoints/helm-releases.api";
|
||||||
import { _i18n } from "../../i18n";
|
import { _i18n } from "../../i18n";
|
||||||
|
import { Notifications } from "../notifications";
|
||||||
|
|
||||||
export interface IChartInstallData {
|
export interface IChartInstallData {
|
||||||
name: string;
|
name: string;
|
||||||
@ -27,45 +28,50 @@ export class InstallChartStore extends DockTabStore<IChartInstallData> {
|
|||||||
});
|
});
|
||||||
autorun(() => {
|
autorun(() => {
|
||||||
const { selectedTab, isOpen } = dockStore;
|
const { selectedTab, isOpen } = dockStore;
|
||||||
if (!isInstallChartTab(selectedTab)) return;
|
if (isInstallChartTab(selectedTab) && isOpen) {
|
||||||
if (isOpen) {
|
this.loadData()
|
||||||
this.loadData();
|
.catch(err => Notifications.error(String(err)))
|
||||||
}
|
}
|
||||||
}, { delay: 250 })
|
}, { delay: 250 })
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
async loadData(tabId = dockStore.selectedTabId) {
|
async loadData(tabId = dockStore.selectedTabId) {
|
||||||
const { values } = this.getData(tabId);
|
const promises = []
|
||||||
const versions = this.versions.getData(tabId);
|
|
||||||
return Promise.all([
|
if (!this.getData(tabId).values) {
|
||||||
!versions && this.loadVersions(tabId),
|
promises.push(this.loadValues(tabId))
|
||||||
!values && this.loadValues(tabId),
|
}
|
||||||
])
|
|
||||||
|
if (!this.versions.getData(tabId)) {
|
||||||
|
promises.push(this.loadVersions(tabId))
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(promises)
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
async loadVersions(tabId: TabId) {
|
async loadVersions(tabId: TabId) {
|
||||||
const { repo, name } = this.getData(tabId);
|
const { repo, name, version } = this.getData(tabId);
|
||||||
this.versions.clearData(tabId); // reset
|
this.versions.clearData(tabId); // reset
|
||||||
const charts = await helmChartsApi.get(repo, name);
|
const charts = await helmChartsApi.get(repo, name, version);
|
||||||
const versions = charts.versions.map(chartVersion => chartVersion.version);
|
const versions = charts.versions.map(chartVersion => chartVersion.version);
|
||||||
this.versions.setData(tabId, versions);
|
this.versions.setData(tabId, versions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
async loadValues(tabId: TabId) {
|
async loadValues(tabId: TabId) {
|
||||||
const data = this.getData(tabId);
|
const data = this.getData(tabId)
|
||||||
const { repo, name, version } = data;
|
const { repo, name, version } = data
|
||||||
let values = "";
|
|
||||||
const fetchValues = async (retry = 1, maxRetries = 3) => {
|
// This loop is for "retrying" the "getValues" call
|
||||||
values = await helmChartsApi.getValues(repo, name, version);
|
for (const _ of Array(3)) {
|
||||||
if (values || retry == maxRetries) return;
|
const values = await helmChartsApi.getValues(repo, name, version)
|
||||||
await fetchValues(retry + 1);
|
if (values) {
|
||||||
};
|
this.setData(tabId, { ...data, values })
|
||||||
this.setData(tabId, { ...data, values: undefined }); // reset
|
return
|
||||||
await fetchValues();
|
}
|
||||||
this.setData(tabId, { ...data, values });
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -107,15 +107,15 @@ export class InstallChart extends Component<Props> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { tabId, chartData, values, versions, install } = this;
|
const { tabId, chartData, values, versions, install } = this;
|
||||||
if (!chartData || chartData.values === undefined || !versions) {
|
if (chartData?.values === undefined || !versions) {
|
||||||
return <Spinner center/>;
|
return <Spinner center />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.releaseDetails) {
|
if (this.releaseDetails) {
|
||||||
return (
|
return (
|
||||||
<div className="InstallChartDone flex column gaps align-center justify-center">
|
<div className="InstallChartDone flex column gaps align-center justify-center">
|
||||||
<p>
|
<p>
|
||||||
<Icon material="check" big sticker/>
|
<Icon material="check" big sticker />
|
||||||
</p>
|
</p>
|
||||||
<p><Trans>Installation complete!</Trans></p>
|
<p><Trans>Installation complete!</Trans></p>
|
||||||
<div className="flex gaps align-center">
|
<div className="flex gaps align-center">
|
||||||
@ -144,7 +144,7 @@ export class InstallChart extends Component<Props> {
|
|||||||
const panelControls = (
|
const panelControls = (
|
||||||
<div className="install-controls flex gaps align-center">
|
<div className="install-controls flex gaps align-center">
|
||||||
<span><Trans>Chart</Trans></span>
|
<span><Trans>Chart</Trans></span>
|
||||||
<Badge label={`${repo}/${name}`} title={_i18n._(t`Repo/Name`)}/>
|
<Badge label={`${repo}/${name}`} title={_i18n._(t`Repo/Name`)} />
|
||||||
<span><Trans>Version</Trans></span>
|
<span><Trans>Version</Trans></span>
|
||||||
<Select
|
<Select
|
||||||
className="chart-version"
|
className="chart-version"
|
||||||
|
|||||||
@ -282,7 +282,6 @@ export class Input extends React.Component<InputProps, State> {
|
|||||||
onKeyDown: this.onKeyDown,
|
onKeyDown: this.onKeyDown,
|
||||||
rows: multiLine ? (rows || 1) : null,
|
rows: multiLine ? (rows || 1) : null,
|
||||||
ref: this.bindRef,
|
ref: this.bindRef,
|
||||||
type: "text",
|
|
||||||
spellCheck: "false",
|
spellCheck: "false",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -116,6 +116,6 @@ export function openServiceAccountKubeConfig(account: ServiceAccount) {
|
|||||||
const namespace = account.getNs()
|
const namespace = account.getNs()
|
||||||
KubeConfigDialog.open({
|
KubeConfigDialog.open({
|
||||||
title: <Trans>{accountName} kubeconfig</Trans>,
|
title: <Trans>{accountName} kubeconfig</Trans>,
|
||||||
loader: () => apiBase.get(`/kubeconfig/service-account/${namespace}/${account}`)
|
loader: () => apiBase.get(`/kubeconfig/service-account/${namespace}/${accountName}`)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -8,10 +8,16 @@ import { JsonApiErrorParsed } from "../../api/json-api";
|
|||||||
export type IMessageId = string | number;
|
export type IMessageId = string | number;
|
||||||
export type IMessage = React.ReactNode | React.ReactNode[] | JsonApiErrorParsed;
|
export type IMessage = React.ReactNode | React.ReactNode[] | JsonApiErrorParsed;
|
||||||
|
|
||||||
|
export enum NotificationStatus {
|
||||||
|
OK = "ok",
|
||||||
|
ERROR = "error",
|
||||||
|
INFO = "info",
|
||||||
|
}
|
||||||
|
|
||||||
export interface INotification {
|
export interface INotification {
|
||||||
id?: IMessageId;
|
id?: IMessageId;
|
||||||
message: IMessage;
|
message: IMessage;
|
||||||
status?: "ok" | "error" | "info";
|
status?: NotificationStatus;
|
||||||
timeout?: number; // auto-hiding timeout in milliseconds, 0 = no hide
|
timeout?: number; // auto-hiding timeout in milliseconds, 0 = no hide
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { reaction } from "mobx";
|
|||||||
import { disposeOnUnmount, observer } from "mobx-react"
|
import { disposeOnUnmount, observer } from "mobx-react"
|
||||||
import { JsonApiErrorParsed } from "../../api/json-api";
|
import { JsonApiErrorParsed } from "../../api/json-api";
|
||||||
import { cssNames, prevDefault } from "../../utils";
|
import { cssNames, prevDefault } from "../../utils";
|
||||||
import { IMessage, INotification, notificationsStore } from "./notifications.store";
|
import { IMessage, INotification, notificationsStore, NotificationStatus } from "./notifications.store";
|
||||||
import { Animate } from "../animate";
|
import { Animate } from "../animate";
|
||||||
import { Icon } from "../icon"
|
import { Icon } from "../icon"
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ export class Notifications extends React.Component {
|
|||||||
notificationsStore.add({
|
notificationsStore.add({
|
||||||
message: message,
|
message: message,
|
||||||
timeout: 2500,
|
timeout: 2500,
|
||||||
status: "ok"
|
status: NotificationStatus.OK
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,13 +25,13 @@ export class Notifications extends React.Component {
|
|||||||
notificationsStore.add({
|
notificationsStore.add({
|
||||||
message: message,
|
message: message,
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
status: "error"
|
status: NotificationStatus.ERROR
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static info(message: IMessage, customOpts: Partial<INotification> = {}) {
|
static info(message: IMessage, customOpts: Partial<INotification> = {}) {
|
||||||
return notificationsStore.add({
|
return notificationsStore.add({
|
||||||
status: "info",
|
status: NotificationStatus.INFO,
|
||||||
timeout: 0,
|
timeout: 0,
|
||||||
message: message,
|
message: message,
|
||||||
...customOpts,
|
...customOpts,
|
||||||
@ -78,7 +78,7 @@ export class Notifications extends React.Component {
|
|||||||
onMouseLeave={() => addAutoHideTimer(notification)}
|
onMouseLeave={() => addAutoHideTimer(notification)}
|
||||||
onMouseEnter={() => removeAutoHideTimer(notification)}>
|
onMouseEnter={() => removeAutoHideTimer(notification)}>
|
||||||
<div className="box center">
|
<div className="box center">
|
||||||
<Icon material="info_outline"/>
|
<Icon material="info_outline" />
|
||||||
</div>
|
</div>
|
||||||
<div className="message box grow">{msgText}</div>
|
<div className="message box grow">{msgText}</div>
|
||||||
<div className="box center">
|
<div className="box center">
|
||||||
|
|||||||
@ -32,6 +32,7 @@ html {
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
box-shadow: 0 0 0 1px $halfGray;
|
box-shadow: 0 0 0 1px $halfGray;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
&--is-focused {
|
&--is-focused {
|
||||||
box-shadow: 0 0 0 2px $primary;
|
box-shadow: 0 0 0 2px $primary;
|
||||||
@ -88,6 +89,7 @@ html {
|
|||||||
|
|
||||||
&__option {
|
&__option {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
background: $primary;
|
background: $primary;
|
||||||
|
|||||||
@ -19,6 +19,8 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
|||||||
kubeWatchApi.addListener(this, this.onWatchApiEvent);
|
kubeWatchApi.addListener(this, this.onWatchApiEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getStatuses?(items: T[]): Record<string, number>;
|
||||||
|
|
||||||
getAllByNs(namespace: string | string[], strict = false): T[] {
|
getAllByNs(namespace: string | string[], strict = false): T[] {
|
||||||
const namespaces: string[] = [].concat(namespace);
|
const namespaces: string[] = [].concat(namespace);
|
||||||
if (namespaces.length) {
|
if (namespaces.length) {
|
||||||
|
|||||||
28
src/renderer/utils/rbac.ts
Normal file
28
src/renderer/utils/rbac.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { KubeResource } from "../../common/rbac";
|
||||||
|
import { _i18n } from "../i18n";
|
||||||
|
|
||||||
|
export const ResourceNames: Record<KubeResource, string> = {
|
||||||
|
"namespaces": _i18n._("Namespaces"),
|
||||||
|
"nodes": _i18n._("Nodes"),
|
||||||
|
"events": _i18n._("Events"),
|
||||||
|
"resourcequotas": _i18n._("Resource Quotas"),
|
||||||
|
"services": _i18n._("Services"),
|
||||||
|
"secrets": _i18n._("Secrets"),
|
||||||
|
"configmaps": _i18n._("Config Maps"),
|
||||||
|
"ingresses": _i18n._("Ingresses"),
|
||||||
|
"networkpolicies": _i18n._("Network Policies"),
|
||||||
|
"persistentvolumes": _i18n._("Persistent Volumes"),
|
||||||
|
"storageclasses": _i18n._("Storage Classes"),
|
||||||
|
"pods": _i18n._("Pods"),
|
||||||
|
"daemonsets": _i18n._("Daemon Sets"),
|
||||||
|
"deployments": _i18n._("Deployments"),
|
||||||
|
"statefulsets": _i18n._("Stateful Sets"),
|
||||||
|
"replicasets": _i18n._("Replica Sets"),
|
||||||
|
"jobs": _i18n._("Jobs"),
|
||||||
|
"cronjobs": _i18n._("Cron Jobs"),
|
||||||
|
"endpoints": _i18n._("Endpoints"),
|
||||||
|
"customresourcedefinitions": _i18n._("Custom Resource Definitions"),
|
||||||
|
"horizontalpodautoscalers": _i18n._("Horizontal Pod Autoscalers"),
|
||||||
|
"podsecuritypolicies": _i18n._("Pod Security Policies"),
|
||||||
|
"poddisruptionbudgets": _i18n._("Pod Disruption Budgets"),
|
||||||
|
}
|
||||||
@ -2,7 +2,26 @@
|
|||||||
|
|
||||||
Here you can find description of changes we've built into each release. While we try our best to make each upgrade automatic and as smooth as possible, there may be some cases where you might need to do something to ensure the application works smoothly. So please read through the release highlights!
|
Here you can find description of changes we've built into each release. While we try our best to make each upgrade automatic and as smooth as possible, there may be some cases where you might need to do something to ensure the application works smoothly. So please read through the release highlights!
|
||||||
|
|
||||||
## 3.6.4 (current version)
|
## 3.6.5-rc.1 (current version)
|
||||||
|
- Fix Notifications not to block items not visually under them from being interacted with
|
||||||
|
- Fix side bar not to scroll after clicking on lower menu item
|
||||||
|
- Auto-select context if only one context is present in pasted Kubeconfig
|
||||||
|
- Fix background image of What's New page on white theme
|
||||||
|
- Reduce height on draggable-top and only render it on macos
|
||||||
|
- Download dir option is now consistent with other settings
|
||||||
|
- Allow to add the same cluster multiple times
|
||||||
|
- Convert bytes in memory chart properly
|
||||||
|
- Fix empty dashboard screen after cluster is removed and added multiple times in a row to application
|
||||||
|
- Dropdowns have pointer cursor now
|
||||||
|
- Proxy kubectl exec requests properly
|
||||||
|
- Pass always chart version information when dealing with helm commands
|
||||||
|
- Fix app crash when conditions are not yet present in CRD objects
|
||||||
|
- Fix kubeconfig generating for service account
|
||||||
|
- Update bundled Helm binary to version 3.3.4
|
||||||
|
- Fix clusters' kubeconfig paths that point to snap config dir to use current snap config path
|
||||||
|
|
||||||
|
|
||||||
|
## 3.6.4
|
||||||
- Fix: deleted namespace does not get auto unselected
|
- Fix: deleted namespace does not get auto unselected
|
||||||
- Get focus to dock tab (terminal & resource editor) content after resize
|
- Get focus to dock tab (terminal & resource editor) content after resize
|
||||||
- Downloading kubectl binary does not block dashboard opening anymore
|
- Downloading kubectl binary does not block dashboard opening anymore
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user