├── .editorconfig
├── .eslintrc.js
├── .gitattributes
├── .github
├── .yamlfmt
├── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ ├── config.yml
│ └── feature_request.yml
├── actions
│ ├── get-token
│ │ └── action.yaml
│ ├── setup-environment
│ │ └── action.yaml
│ ├── spelling
│ │ ├── README.md
│ │ ├── advice.md
│ │ ├── allow.txt
│ │ ├── candidate.patterns
│ │ ├── excludes.txt
│ │ ├── expect.txt
│ │ ├── line_forbidden.patterns
│ │ ├── patterns.txt
│ │ └── reject.txt
│ └── yarn-install
│ │ └── action.yaml
├── dependabot.yml
└── workflows
│ ├── bats.yaml
│ ├── bats
│ ├── get-tests.py
│ ├── sanitize-artifact-name.sh
│ └── summarize.mjs
│ ├── codeql.yaml
│ ├── docker-cli-monitor.yaml
│ ├── go-work-sync.yaml
│ ├── k3s-versions.yaml
│ ├── linux-e2e.yaml
│ ├── linux-release.yaml
│ ├── macM1-e2e.yaml
│ ├── package.yaml
│ ├── paths-ignore.yaml
│ ├── rddepman.yaml
│ ├── rdx-host-api-tests.yaml
│ ├── release-merge-to-main.yaml
│ ├── scorecard.yml
│ ├── screenshot.yaml
│ ├── smoke-test.yaml
│ ├── smoke-test
│ └── smoke-test.sh
│ ├── spelling.yml
│ ├── test.yaml
│ ├── ucmonitor.yaml
│ ├── upgrade-generate.yaml
│ └── windows-e2e.yaml
├── .gitignore
├── .gitmodules
├── .golangci.yaml
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── babel.config.js
├── background.ts
├── bats
├── Makefile
├── README.md
├── scripts
│ ├── bats-lint.pl
│ └── ghcr-mirror.sh
└── tests
│ ├── compose
│ ├── compose.bats
│ └── testdata
│ │ ├── Dockerfile.nginx
│ │ ├── app
│ │ ├── Dockerfile
│ │ ├── app.py
│ │ └── requirements.txt
│ │ ├── compose.yaml
│ │ └── nginx.conf
│ ├── containers
│ ├── allowed-images.bats
│ ├── auto-start.bats
│ ├── catch-duplicate-api-patterns.bats
│ ├── docker-buildx-python3-uname.bats
│ ├── factory-reset-containerd-shims.bats
│ ├── factory-reset-snapshots.bats
│ ├── factory-reset.bats
│ ├── host-connectivity.bats
│ ├── host-network-ports.bats
│ ├── init.bats
│ ├── platform.bats
│ ├── published-ports.bats
│ ├── run-rancher.bats
│ ├── split-dns-vpn.bats
│ ├── switch-engines.bats
│ ├── volumes.bats
│ └── wasm.bats
│ ├── extensions
│ ├── allow-list.bats
│ ├── containers.bats
│ ├── install.bats
│ └── testdata
│ │ ├── Dockerfile
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── basic.json
│ │ ├── bin
│ │ ├── dummy.go
│ │ ├── dummy.sh
│ │ └── server.go
│ │ ├── compose.yaml
│ │ ├── everything.json
│ │ ├── extension-icon.svg
│ │ ├── host-apis.json
│ │ ├── host-binaries.json
│ │ ├── missing-icon-file.json
│ │ ├── missing-icon.json
│ │ ├── ui.json
│ │ ├── ui
│ │ ├── host-apis.html
│ │ └── index.html
│ │ ├── vm-compose.json
│ │ └── vm-image.json
│ ├── helpers
│ ├── commands.bash
│ ├── defaults.bash
│ ├── images.bash
│ ├── info.bash
│ ├── kubernetes.bash
│ ├── kubernetes.bats
│ ├── load.bash
│ ├── os.bash
│ ├── paths.bash
│ ├── profile.bash
│ ├── snapshots.bash
│ ├── utils.bash
│ ├── utils.bats
│ └── vm.bash
│ ├── k8s
│ ├── enable-disable-k8s.bats
│ ├── foreach-k3s-version.bats
│ ├── helm-install-rancher.bats
│ ├── port-forwarding.bats
│ ├── specify-invalid-k8s-version.bats
│ ├── spinkube-npm.bats
│ ├── spinkube.bats
│ ├── traefik.bats
│ ├── up-downgrade-k8s.bats
│ ├── wasm.bats
│ └── wordpress.bats
│ ├── preferences
│ ├── move-from-roaming-to-local.bats
│ ├── surface-invalid-args.bats
│ ├── verify-paths.bats
│ └── verify-settings.bats
│ ├── profile
│ ├── create-profile-output.bats
│ ├── deployment.bats
│ ├── invalid-locked-k8s-version.bats
│ └── wasm.bats
│ ├── registry
│ └── creds.bats
│ ├── snapshots
│ ├── create-use-snapshot.bats
│ ├── restore-snapshot-after-factory-reset.bats
│ ├── test-snapshot-list.bats
│ └── test_rdctl_snapshot.bats
│ └── utils
│ └── spin.bats
├── build
├── electron-publisher-custom.js
├── license.rtf
├── signing-config-mac.yaml
├── signing-config-win.yaml
└── wix
│ ├── bannrbmp.png
│ ├── dialogs.wxs
│ ├── dlgbmp.png
│ ├── main.wxs
│ ├── scope.wxs
│ ├── string-overrides.wxl
│ ├── verify.wxs
│ └── welcome.wxs
├── dev-app-update.yml
├── docs
├── assets
│ └── images
│ │ └── contributing
│ │ ├── e2e-failure-reports.png
│ │ └── e2e-summary.png
├── development
│ ├── README.md
│ ├── env.md
│ ├── factory-reset.md
│ ├── features.md
│ ├── linux-release-process.md
│ ├── obs.md
│ ├── release-checklist.md
│ └── signing.md
└── networking
│ └── windows
│ ├── README.md
│ ├── rancher-desktop-guest-agent.md
│ └── rancher-desktop-networking.md
├── e2e
├── assets
│ └── k8s-deploy-sample
│ │ └── nginx-sample-app.yaml
├── backend.e2e.spec.ts
├── config
│ └── playwright-config.ts
├── credentials-server.e2e.spec.ts
├── extensions.e2e.spec.ts
├── lockedFields.e2e.spec.ts
├── main.e2e.spec.ts
├── pages
│ ├── containers-page.ts
│ ├── diagnostics-page.ts
│ ├── extensions-page.ts
│ ├── images-page.ts
│ ├── k8s-page.ts
│ ├── nav-page.ts
│ ├── portforward-page.ts
│ ├── preferences
│ │ ├── application.ts
│ │ ├── containerEngine.ts
│ │ ├── index.ts
│ │ ├── kubernetes.ts
│ │ ├── virtualMachine.ts
│ │ └── wsl.ts
│ ├── snapshots-page.ts
│ ├── troubleshooting-page.ts
│ └── wsl-integrations-page.ts
├── preferences.e2e.spec.ts
├── quit-on-close.e2e.spec.ts
├── rdctl.e2e.spec.ts
├── start-in-background.e2e.spec.ts
├── startup-profiles.e2e.spec.ts
├── utils
│ ├── ProfileUtils.ts
│ └── TestUtils.ts
└── wsl-integrations.e2e.spec.ts
├── go.work
├── jest.config.js
├── nuxt.config.js
├── package.json
├── packaging
├── electron-builder.yml
└── linux
│ ├── appimage.yml
│ ├── flatpak.yaml
│ ├── rancher-desktop.appdata.xml
│ └── rancher-desktop.spec
├── pkg
└── rancher-desktop
│ ├── assets
│ ├── dependencies.yaml
│ ├── extension-data.yaml
│ ├── fonts
│ │ ├── lato
│ │ │ ├── lato-v17-latin-700.woff
│ │ │ ├── lato-v17-latin-700.woff2
│ │ │ ├── lato-v17-latin-regular.woff
│ │ │ └── lato-v17-latin-regular.woff2
│ │ ├── poppins
│ │ │ ├── poppins-v15-latin-300.woff
│ │ │ ├── poppins-v15-latin-300.woff2
│ │ │ ├── poppins-v15-latin-500.woff
│ │ │ └── poppins-v15-latin-500.woff2
│ │ └── roboto-mono
│ │ │ ├── roboto-mono-v13-latin-regular.woff
│ │ │ └── roboto-mono-v13-latin-regular.woff2
│ ├── images
│ │ ├── kubernetes-black.svg
│ │ └── logo.svg
│ ├── lima-config.yaml
│ ├── networks-config.yaml
│ ├── scripts
│ │ ├── 10-flannel.conflist
│ │ ├── buildkit.confd
│ │ ├── buildkit.initd
│ │ ├── cert-manager.yaml
│ │ ├── configure-allowed-images
│ │ ├── docker-credential-rancher-desktop
│ │ ├── install-containerd-shims
│ │ ├── install-k3s
│ │ ├── install-wsl-helpers
│ │ ├── k3s-containerd-config.toml
│ │ ├── logrotate-k3s
│ │ ├── logrotate-lima-guestagent
│ │ ├── logrotate-openresty
│ │ ├── moproxy.initd
│ │ ├── nerdctl
│ │ ├── nginx.conf
│ │ ├── rancher-desktop-guestagent.initd
│ │ ├── service-cri-dockerd.initd
│ │ ├── service-k3s.initd
│ │ ├── service-wsl-dockerd.initd
│ │ ├── spin-operator.yaml
│ │ ├── wsl-data.conf
│ │ ├── wsl-exec
│ │ └── wsl-init
│ ├── specs
│ │ ├── README.md
│ │ └── command-api.yaml
│ ├── styles
│ │ ├── app.scss
│ │ ├── base
│ │ │ ├── _basic.scss
│ │ │ ├── _color.scss
│ │ │ ├── _functions.scss
│ │ │ ├── _helpers.scss
│ │ │ ├── _mixins.scss
│ │ │ ├── _typography.scss
│ │ │ └── _variables.scss
│ │ ├── fonts
│ │ │ ├── _dots.scss
│ │ │ ├── _fontstack.scss
│ │ │ ├── _icons.scss
│ │ │ └── _zerowidthspace.scss
│ │ ├── global
│ │ │ ├── _button.scss
│ │ │ ├── _cards.scss
│ │ │ ├── _columns.scss
│ │ │ ├── _form.scss
│ │ │ ├── _gauges.scss
│ │ │ ├── _labeled-input.scss
│ │ │ ├── _resource.scss
│ │ │ ├── _select.scss
│ │ │ ├── _table.scss
│ │ │ └── _tooltip.scss
│ │ ├── rancher-desktop.scss
│ │ ├── themes
│ │ │ ├── _dark.scss
│ │ │ ├── _light.scss
│ │ │ └── _suse.scss
│ │ └── vendor
│ │ │ ├── normalize.scss
│ │ │ ├── vue-js-modal.scss
│ │ │ ├── vue-js-modal
│ │ │ └── styles.css
│ │ │ └── vue-select.scss
│ └── translations
│ │ ├── en-us.yaml
│ │ └── zh-hans.yaml
│ ├── backend
│ ├── __tests__
│ │ └── k3sHelper.spec.ts
│ ├── backend.ts
│ ├── backendHelper.ts
│ ├── containerClient
│ │ ├── __tests__
│ │ │ ├── auth.spec.ts
│ │ │ ├── client.spec.ts
│ │ │ └── registry.spec.ts
│ │ ├── auth.ts
│ │ ├── index.ts
│ │ ├── mobyClient.ts
│ │ ├── nerdctlClient.ts
│ │ ├── registry.ts
│ │ └── types.ts
│ ├── factory.ts
│ ├── images
│ │ ├── imageFactory.ts
│ │ ├── imageProcessor.ts
│ │ ├── mobyImageProcessor.ts
│ │ └── nerdctlImageProcessor.ts
│ ├── k3sHelper.ts
│ ├── k8s.ts
│ ├── kube
│ │ ├── client.ts
│ │ ├── lima.ts
│ │ └── wsl.ts
│ ├── kubeconfig.ts
│ ├── lima.ts
│ ├── mock.ts
│ ├── mock_screenshots.ts
│ ├── progressTracker.ts
│ ├── steve.ts
│ └── wsl.ts
│ ├── components
│ ├── ActionDropdown.vue
│ ├── ActionMenu.vue
│ ├── Alert.vue
│ ├── BackendProgress.vue
│ ├── DashboardOpen.vue
│ ├── DiagnosticsBody.vue
│ ├── DiagnosticsButtonRun.vue
│ ├── EmptyState.vue
│ ├── EngineSelector.vue
│ ├── ExtensionsError.vue
│ ├── ExtensionsUninstalled.vue
│ ├── Help.vue
│ ├── ImageAddTabs.vue
│ ├── Images.vue
│ ├── ImagesButtonAdd.vue
│ ├── ImagesFormAdd.vue
│ ├── ImagesOutputWindow.vue
│ ├── ImagesScanResults.vue
│ ├── IncompatiblePreferencesAlert.vue
│ ├── LoadingIndicator.vue
│ ├── MarketplaceCard.vue
│ ├── MarketplaceCatalog.vue
│ ├── MountTypeSelector.vue
│ ├── Nav.vue
│ ├── NavIconExtension.vue
│ ├── NavItem.vue
│ ├── NetworkStatus.vue
│ ├── Notifications.vue
│ ├── PathManagementSelector.vue
│ ├── PortForwarding.vue
│ ├── Preferences
│ │ ├── Alert.vue
│ │ ├── ApplicationBehavior.vue
│ │ ├── ApplicationEnvironment.vue
│ │ ├── ApplicationGeneral.vue
│ │ ├── BodyApplication.vue
│ │ ├── BodyContainerEngine.vue
│ │ ├── BodyKubernetes.vue
│ │ ├── BodyVirtualMachine.vue
│ │ ├── BodyWsl.vue
│ │ ├── ButtonOpen.vue
│ │ ├── ContainerEngineAllowedImages.vue
│ │ ├── ContainerEngineGeneral.vue
│ │ ├── Help.vue
│ │ ├── ModalBody.vue
│ │ ├── ModalFooter.vue
│ │ ├── ModalHeader.vue
│ │ ├── ModalNav.vue
│ │ ├── ModalNavItem.vue
│ │ ├── VirtualMachineEmulation.vue
│ │ ├── VirtualMachineHardware.vue
│ │ ├── VirtualMachineVolumes.vue
│ │ ├── WslIntegrations.vue
│ │ └── WslProxy.vue
│ ├── Progress.vue
│ ├── RdInput.vue
│ ├── RdSelect.vue
│ ├── SnapshotCard.vue
│ ├── Snapshots.vue
│ ├── SnapshotsButtonCreate.vue
│ ├── SortableTable
│ │ ├── THead.vue
│ │ ├── actions.js
│ │ ├── filtering.js
│ │ ├── grouping.js
│ │ ├── index.vue
│ │ ├── paging.js
│ │ ├── selection.js
│ │ └── sorting.js
│ ├── StatusBar.vue
│ ├── StatusBarItem.vue
│ ├── SystemPreferences.vue
│ ├── Tabbed
│ │ ├── RdTabbed.vue
│ │ ├── Tab.vue
│ │ └── index.vue
│ ├── TelemetryOptIn.vue
│ ├── TheTitle.vue
│ ├── TroubleshootingLineItem.vue
│ ├── UpdateStatus.vue
│ ├── Version.vue
│ ├── WSLIntegration.vue
│ ├── __tests__
│ │ ├── PreferencesButton.spec.ts
│ │ ├── StatusBar.spec.ts
│ │ ├── SystemPreferences.spec.js
│ │ └── UpdateStatus.spec.ts
│ └── form
│ │ ├── LabeledBadge.vue
│ │ ├── LabeledTooltip.vue
│ │ ├── RdCheckbox.vue
│ │ ├── RdFieldset.vue
│ │ ├── RdSlider.vue
│ │ ├── SplitButton.vue
│ │ ├── TextAreaAutoGrow.vue
│ │ ├── TooltipIcon.vue
│ │ └── __tests__
│ │ └── SplitButton.spec.ts
│ ├── config
│ ├── __tests__
│ │ ├── commandLineOptions.spec.ts
│ │ ├── settings.spec.ts
│ │ └── settingsMigrations.spec.ts
│ ├── commandLineOptions.ts
│ ├── cookies.js
│ ├── emptyStubForJSLinter.js
│ ├── help.ts
│ ├── private-label.js
│ ├── query-params.js
│ ├── settings.ts
│ ├── settingsImpl.ts
│ ├── transientSettings.ts
│ └── types.js
│ ├── hocs
│ ├── README.md
│ └── withCredentials.ts
│ ├── index.ts
│ ├── integrations
│ ├── __tests__
│ │ ├── manageLinesInFile.spec.ts
│ │ ├── pathManager.spec.ts
│ │ ├── unixIntegrationManager.spec.ts
│ │ └── windowsIntegrationManager.spec.ts
│ ├── integrationManager.ts
│ ├── manageLinesInFile.ts
│ ├── pathManager.ts
│ ├── pathManagerImpl.ts
│ ├── unixIntegrationManager.ts
│ └── windowsIntegrationManager.ts
│ ├── layouts
│ ├── default.vue
│ ├── dialog.vue
│ └── preferences.vue
│ ├── main
│ ├── __tests__
│ │ ├── deploymentProfiles.spec.ts
│ │ └── ipcMain.spec.ts
│ ├── commandServer
│ │ ├── __tests__
│ │ │ └── settingsValidator.spec.ts
│ │ ├── httpCommandServer.ts
│ │ └── settingsValidator.ts
│ ├── credentialServer
│ │ ├── README.md
│ │ ├── __tests__
│ │ │ └── credentialUtils.spec.ts
│ │ ├── credentialUtils.ts
│ │ └── httpCredentialHelperServer.ts
│ ├── dashboardServer
│ │ ├── index.ts
│ │ └── proxyUtils.ts
│ ├── deploymentProfiles.ts
│ ├── diagnostics
│ │ ├── __tests__
│ │ │ ├── diagnostics.spec.ts
│ │ │ ├── dockerCliSymlinks.spec.ts
│ │ │ └── rdBinInShell.spec.ts
│ │ ├── connectedToInternet.ts
│ │ ├── diagnostics.ts
│ │ ├── dockerCliSymlinks.ts
│ │ ├── integrationsWindows.ts
│ │ ├── kubeConfigSymlink.ts
│ │ ├── kubeContext.ts
│ │ ├── kubeVersionsAvailable.ts
│ │ ├── limaDarwin.ts
│ │ ├── mockForScreenshots.ts
│ │ ├── pathManagement.ts
│ │ ├── rdBinInShell.ts
│ │ ├── testCheckers.ts
│ │ ├── types.ts
│ │ └── wslFromStore.ts
│ ├── extensions
│ │ ├── __tests__
│ │ │ ├── extensions.spec.ts
│ │ │ └── manager.spec.ts
│ │ ├── extensions.ts
│ │ ├── index.ts
│ │ ├── manager.ts
│ │ └── types.ts
│ ├── imageEvents.ts
│ ├── ipcMain.ts
│ ├── mainEvents.ts
│ ├── mainmenu.ts
│ ├── networking
│ │ ├── __tests__
│ │ │ └── mac-ca.spec.ts
│ │ ├── cert-parse.ts
│ │ ├── index.ts
│ │ ├── mac-ca.ts
│ │ ├── proxy.ts
│ │ └── win-ca.ts
│ ├── serverHelper.ts
│ ├── snapshots
│ │ ├── snapshots.ts
│ │ └── types.ts
│ ├── tray.ts
│ └── update
│ │ ├── LonghornProvider.ts
│ │ ├── MSIUpdater.ts
│ │ ├── __tests__
│ │ └── LonghornProvider.spec.ts
│ │ └── index.ts
│ ├── middleware
│ ├── i18n.js
│ └── indexRedirect.js
│ ├── mixins
│ ├── labeled-form-element.js
│ └── vue-select-overrides.js
│ ├── nuxt
│ ├── App.js
│ ├── LICENSE
│ ├── client.js
│ ├── components
│ │ ├── nuxt-build-indicator.vue
│ │ ├── nuxt-child.js
│ │ ├── nuxt-error.vue
│ │ ├── nuxt-link.client.js
│ │ ├── nuxt-link.server.js
│ │ └── nuxt.js
│ ├── cookie-universal-nuxt.js
│ ├── empty.js
│ ├── index.js
│ ├── jsonp.js
│ ├── middleware.js
│ ├── mixins
│ │ ├── fetch.client.js
│ │ └── fetch.server.js
│ ├── router.scrollBehavior.js
│ ├── server.js
│ ├── store.js
│ ├── utils.js
│ └── views
│ │ ├── app.template.html
│ │ └── error.html
│ ├── pages
│ ├── Containers.vue
│ ├── DenyRoot.vue
│ ├── Diagnostics.vue
│ ├── Dialog.vue
│ ├── Extensions.vue
│ ├── FirstRun.vue
│ ├── General.vue
│ ├── Images.vue
│ ├── KubernetesError.vue
│ ├── PortForwarding.vue
│ ├── Preferences.vue
│ ├── Snapshots.vue
│ ├── SudoPrompt.vue
│ ├── Troubleshooting.vue
│ ├── UnmetPrerequisites.vue
│ ├── extensions
│ │ ├── _root
│ │ │ └── _src
│ │ │ │ └── _id.vue
│ │ └── installed.vue
│ ├── images
│ │ ├── add.vue
│ │ └── scans
│ │ │ └── _image-name.vue
│ └── snapshots
│ │ ├── create.vue
│ │ └── dialog.vue
│ ├── plugins
│ ├── clean-html-directive.js
│ ├── directives.js
│ ├── extend-router.js
│ ├── i18n.js
│ ├── shortkey.js
│ ├── tooltip.js
│ ├── trim-whitespace.js
│ ├── v-select.js
│ └── vue-js-modal.js
│ ├── preload
│ ├── README.md
│ ├── extensions.ts
│ └── index.ts
│ ├── product.js
│ ├── public
│ └── index.html
│ ├── router.js
│ ├── store
│ ├── action-menu.js
│ ├── applicationSettings.ts
│ ├── credentials.ts
│ ├── diagnostics.ts
│ ├── extensions.ts
│ ├── i18n.js
│ ├── imageManager.js
│ ├── k8sManager.js
│ ├── page.ts
│ ├── preferences.ts
│ ├── prefs.js
│ ├── snapshots.ts
│ ├── transientSettings.ts
│ └── ts-helpers.ts
│ ├── sudo-prompt
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── index.d.ts
│ ├── index.js
│ ├── linux.png
│ ├── macos.png
│ ├── package.json
│ ├── test-concurrent.js
│ ├── test.js
│ └── windows.png
│ ├── tsconfig.json
│ ├── typings
│ ├── assets.d.ts
│ ├── electron-ipc.d.ts
│ ├── linux-ca.d.ts
│ ├── shell.d.ts
│ ├── shims-vue.d.ts
│ ├── store.d.ts
│ ├── unix.interface.ts
│ └── vue-i18n.ts
│ ├── utils
│ ├── DownloadProgressListener.ts
│ ├── __tests__
│ │ ├── assets
│ │ │ └── safeRename
│ │ │ │ └── safeRename.tar
│ │ ├── childProcess.spec.ts
│ │ ├── dockerDirManager.spec.ts
│ │ ├── dockerUtils.spec.ts
│ │ ├── iterator.spec.ts
│ │ ├── kubeVersions.spec.ts
│ │ ├── paths.spec.ts
│ │ └── safeRename.spec.ts
│ ├── array.js
│ ├── backgroundProcess.ts
│ ├── childProcess.ts
│ ├── clone.ts
│ ├── commandLine.ts
│ ├── dateUtils.ts
│ ├── dockerDirManager.ts
│ ├── dockerUtils.ts
│ ├── environment.ts
│ ├── eventEmitter.ts
│ ├── fetch.ts
│ ├── filters.ts
│ ├── imageOutputCuller.js
│ ├── ipcRenderer.ts
│ ├── iterator.ts
│ ├── kubeVersions.ts
│ ├── latch.ts
│ ├── logging.ts
│ ├── networks.ts
│ ├── object.js
│ ├── osVersion.ts
│ ├── paths.ts
│ ├── platform.js
│ ├── position.js
│ ├── processOutputInterpreters
│ │ ├── __tests__
│ │ │ ├── assets
│ │ │ │ ├── build.txt
│ │ │ │ ├── pull.txt
│ │ │ │ ├── pull03.txt
│ │ │ │ ├── pull2.txt
│ │ │ │ ├── push.txt
│ │ │ │ ├── trivy-image-metric-server-input.txt
│ │ │ │ ├── trivy-image-metric-server-output.txt
│ │ │ │ ├── trivy-image-postgres-input.txt
│ │ │ │ └── trivy-image-postgres-output.txt
│ │ │ ├── image-build-output.spec.js
│ │ │ ├── image-non-build-output.spec.js
│ │ │ └── trivy-image-output.spec.js
│ │ ├── image-build-output.js
│ │ ├── image-non-build-output.js
│ │ └── trivy-image-output.ts
│ ├── protocols.ts
│ ├── resources.ts
│ ├── safeRename.ts
│ ├── shortcuts.ts
│ ├── sort.js
│ ├── string-encode.ts
│ ├── string.js
│ ├── stringify.ts
│ ├── testUtils
│ │ ├── mockResources.ts
│ │ └── setupElectron.ts
│ ├── typeUtils.ts
│ ├── units.js
│ ├── version.ts
│ └── wslVersion.ts
│ ├── vue.config.js
│ └── window
│ ├── constants.ts
│ ├── dashboard.ts
│ ├── index.ts
│ ├── preferenceConstants.ts
│ └── preferences.ts
├── resources
├── darwin
│ └── bin
│ │ ├── nerdctl
│ │ └── spin
├── icons
│ ├── containerd-icon-color.png
│ ├── issue-opened-16.png
│ ├── issue-opened-16.svg
│ ├── issue-opened-16@2x.png
│ ├── kubernetes-icon-black-orig.png
│ ├── kubernetes-icon-black.png
│ ├── kubernetes-icon-color-orig.png
│ ├── kubernetes-icon-color.png
│ ├── logo-square-512.png
│ ├── logo-square-bw.png
│ ├── logo-square-bw@1.25x.png
│ ├── logo-square-bw@1.5x.png
│ ├── logo-square-bw@2.png
│ ├── logo-square-red.png
│ ├── logo-square-red@1.25x.png
│ ├── logo-square-red@1.5x.png
│ ├── logo-square-red@2x.png
│ ├── logo-square.png
│ ├── logo-square@1.25x.png
│ ├── logo-square@1.5x.png
│ ├── logo-square@2x.png
│ ├── logo-tray-Template@2x.png
│ ├── logo-tray-error-Template@2x.png
│ ├── logo-tray-starting-Template@2x.png
│ ├── logo-tray-stopped-Template@2x.png
│ ├── logo-tray-stopping-Template@2x.png
│ └── mac-icon.png
├── k3s-versions.json
├── linux
│ └── bin
│ │ ├── nerdctl
│ │ └── spin
└── setup-spin
├── screenshots
├── README.md
├── Screenshots.ts
├── extensions
│ └── logs-explorer-0.2.2.png
├── playwright-config.ts
├── screenshot.ps1
├── screenshots.e2e.spec.ts
└── test-data
│ ├── containers.ts
│ ├── preferences.ts
│ └── snapshots.ts
├── scripts
├── assets
│ ├── extension-data.yaml
│ └── options.go.templ
├── build.ts
├── check-api-schema.ts
├── dependencies
│ ├── go-source.ts
│ ├── lima.ts
│ ├── moby-openapi.ts
│ ├── sudo-prompt.ts
│ ├── tar-archives.ts
│ ├── tools.ts
│ ├── wix.ts
│ └── wsl.ts
├── dev.ts
├── docker-cli-monitor.ts
├── e2e.ts
├── extension-data.ts
├── generateCliCode.ts
├── go-license-check.sh
├── go.mod
├── go.sum
├── install-latest-ci.sh
├── k3s-versions.go
├── k3s-versions.sh
├── lib
│ ├── build-utils.ts
│ ├── dependencies.ts
│ ├── download.ts
│ ├── extension-data.ts
│ ├── installer-win32-gen.tsx
│ ├── installer-win32.tsx
│ ├── sign-macos.ts
│ └── sign-win32.ts
├── lint-go.ts
├── node-license-check.sh
├── package.ts
├── populate-update-server.ts
├── postinstall.ts
├── rddepman.ts
├── release-merge-to-main.ts
├── sign.ts
├── simple_process.ts
├── spelling.sh
├── ts-wrapper.js
├── unreleased-change-monitor.ts
├── windows-setup.ps1
├── windows
│ ├── generate-nerdctl-stub.ps1
│ ├── install-wsl.ps1
│ ├── restart-helpers.ps1
│ ├── sudo-install-wsl.ps1
│ └── uninstall-wsl.ps1
└── wix.ts
├── src
├── go
│ ├── docker-credential-none
│ │ ├── dcnone
│ │ │ ├── dcnone.go
│ │ │ ├── dcnone_test.go
│ │ │ └── helpers.go
│ │ ├── go.mod
│ │ ├── go.sum
│ │ └── main.go
│ ├── extension-proxy
│ │ ├── README.md
│ │ ├── go.mod
│ │ └── main.go
│ ├── guestagent
│ │ ├── README.md
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── main.go
│ │ └── pkg
│ │ │ ├── containerd
│ │ │ ├── events_linux.go
│ │ │ └── events_stub.go
│ │ │ ├── docker
│ │ │ └── events.go
│ │ │ ├── forwarder
│ │ │ ├── forwarder.go
│ │ │ ├── serviceapi.go
│ │ │ └── wslproxy.go
│ │ │ ├── iptables
│ │ │ ├── iptables.go
│ │ │ ├── iptables_test.go
│ │ │ └── scanner.go
│ │ │ ├── kube
│ │ │ ├── servicewatcher_linux.go
│ │ │ ├── watcher_linux.go
│ │ │ └── watcher_stub.go
│ │ │ ├── procnet
│ │ │ ├── scanner_linux.go
│ │ │ └── scanner_stub.go
│ │ │ ├── tracker
│ │ │ ├── apitracker.go
│ │ │ ├── apitracker_test.go
│ │ │ ├── portstorage.go
│ │ │ └── tracker.go
│ │ │ ├── types
│ │ │ ├── README.md
│ │ │ └── portmapping.go
│ │ │ └── utils
│ │ │ └── utils.go
│ ├── mock-wsl
│ │ ├── README.md
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── lock_file_other.go
│ │ ├── lock_file_windows.go
│ │ ├── mock-wsl.go
│ │ └── schema.json
│ ├── nerdctl-stub
│ │ ├── README.md
│ │ ├── command_handlers.go
│ │ ├── command_handlers_test.go
│ │ ├── debugging.go
│ │ ├── debugging_stub.go
│ │ ├── generate
│ │ │ ├── README.md
│ │ │ ├── go.mod
│ │ │ ├── go.sum
│ │ │ ├── main_linux.go
│ │ │ └── main_stub.go
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── main.go
│ │ ├── main_linux.go
│ │ ├── main_shared.go
│ │ ├── main_shared_test.go
│ │ ├── main_unsupported.go
│ │ ├── main_windows.go
│ │ ├── nerdctl_commands_generated.go
│ │ ├── parse_args.go
│ │ └── parse_args_test.go
│ ├── networking
│ │ ├── .github
│ │ │ └── workflows
│ │ │ │ ├── go.yaml
│ │ │ │ └── release.yaml
│ │ ├── .gitignore
│ │ ├── LICENSE
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── cmd
│ │ │ ├── host
│ │ │ │ ├── config_windows.go
│ │ │ │ └── switch_windows.go
│ │ │ ├── network
│ │ │ │ └── setup_linux.go
│ │ │ ├── proxy
│ │ │ │ └── wsl_integration_linux.go
│ │ │ └── vm
│ │ │ │ └── switch_linux.go
│ │ ├── go.mod
│ │ ├── go.sum
│ │ └── pkg
│ │ │ ├── config
│ │ │ └── config.go
│ │ │ ├── log
│ │ │ └── log.go
│ │ │ ├── portproxy
│ │ │ ├── server.go
│ │ │ └── server_test.go
│ │ │ ├── utils
│ │ │ └── pipe.go
│ │ │ └── vsock
│ │ │ ├── conn_windows.go
│ │ │ ├── constants.go
│ │ │ └── handshake_windows.go
│ ├── rdctl
│ │ ├── README.md
│ │ ├── cmd
│ │ │ ├── api.go
│ │ │ ├── createProfile.go
│ │ │ ├── extension.go
│ │ │ ├── extensionInstall.go
│ │ │ ├── extensionList.go
│ │ │ ├── extensionUninstall.go
│ │ │ ├── factoryReset.go
│ │ │ ├── internal.go
│ │ │ ├── internalProcess.go
│ │ │ ├── internalProcessWaitKill.go
│ │ │ ├── listSettings.go
│ │ │ ├── paths.go
│ │ │ ├── root.go
│ │ │ ├── set.go
│ │ │ ├── setup.go
│ │ │ ├── shell.go
│ │ │ ├── shutdown.go
│ │ │ ├── snapshot.go
│ │ │ ├── snapshotCreate.go
│ │ │ ├── snapshotDelete.go
│ │ │ ├── snapshotList.go
│ │ │ ├── snapshotList_test.go
│ │ │ ├── snapshotRestore.go
│ │ │ ├── snapshotUnlock.go
│ │ │ ├── start.go
│ │ │ └── version.go
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── main.go
│ │ └── pkg
│ │ │ ├── autostart
│ │ │ ├── autostart_darwin.go
│ │ │ ├── autostart_linux.go
│ │ │ └── autostart_windows.go
│ │ │ ├── client
│ │ │ ├── client.go
│ │ │ ├── handle_unix.go
│ │ │ ├── handle_windows.go
│ │ │ └── utils.go
│ │ │ ├── config
│ │ │ └── config.go
│ │ │ ├── directories
│ │ │ ├── directories.go
│ │ │ ├── directories_test.go
│ │ │ ├── directories_windows.go
│ │ │ ├── directories_windows_test.go
│ │ │ ├── empty.go
│ │ │ └── lima_home.go
│ │ │ ├── factoryreset
│ │ │ ├── delete_data.go
│ │ │ ├── delete_data_darwin.go
│ │ │ ├── delete_data_linux.go
│ │ │ ├── delete_data_unix.go
│ │ │ ├── delete_data_unix_test.go
│ │ │ ├── delete_data_windows.go
│ │ │ ├── factory_reset_unix.go
│ │ │ └── factory_reset_windows.go
│ │ │ ├── lima
│ │ │ └── name.go
│ │ │ ├── lock
│ │ │ ├── lock.go
│ │ │ └── mock.go
│ │ │ ├── options
│ │ │ └── generated
│ │ │ │ └── doc.go
│ │ │ ├── paths
│ │ │ ├── paths.go
│ │ │ ├── paths_darwin.go
│ │ │ ├── paths_darwin_test.go
│ │ │ ├── paths_linux.go
│ │ │ ├── paths_linux_test.go
│ │ │ ├── paths_test.go
│ │ │ ├── paths_unix.go
│ │ │ ├── paths_windows.go
│ │ │ └── paths_windows_test.go
│ │ │ ├── plist
│ │ │ ├── plist.go
│ │ │ └── plist_test.go
│ │ │ ├── process
│ │ │ ├── process_darwin.go
│ │ │ ├── process_linux.go
│ │ │ ├── process_test.go
│ │ │ ├── process_unix.go
│ │ │ ├── process_windows.go
│ │ │ └── process_windows_test.go
│ │ │ ├── reg
│ │ │ ├── reg.go
│ │ │ └── reg_test.go
│ │ │ ├── runner
│ │ │ ├── runner.go
│ │ │ └── runner_test.go
│ │ │ ├── shutdown
│ │ │ └── shutdown.go
│ │ │ ├── snapshot
│ │ │ ├── copyFile_darwin.go
│ │ │ ├── copyFile_linux.go
│ │ │ ├── manager.go
│ │ │ ├── manager_test.go
│ │ │ ├── manager_unix_test.go
│ │ │ ├── manager_windows_test.go
│ │ │ ├── snapshot.go
│ │ │ ├── snapshotter.go
│ │ │ ├── snapshotter_unix.go
│ │ │ └── snapshotter_windows.go
│ │ │ ├── utils
│ │ │ └── utils.go
│ │ │ ├── version
│ │ │ └── version.go
│ │ │ └── wsl
│ │ │ ├── doc.go
│ │ │ ├── mock_windows.go
│ │ │ ├── names.go
│ │ │ └── wsl_windows.go
│ ├── spin-stub
│ │ ├── README.md
│ │ ├── go.mod
│ │ └── main.go
│ └── wsl-helper
│ │ ├── .gitignore
│ │ ├── cmd
│ │ ├── certificates_windows.go
│ │ ├── dockerproxy.go
│ │ ├── dockerproxy_kill_linux.go
│ │ ├── dockerproxy_serve_linux.go
│ │ ├── dockerproxy_serve_windows.go
│ │ ├── dockerproxy_start.go
│ │ ├── enum.go
│ │ ├── k3s.go
│ │ ├── k3s_kubeconfig.go
│ │ ├── kubeconfig.go
│ │ ├── process_kill_windows.go
│ │ ├── process_spawn_windows.go
│ │ ├── process_windows.go
│ │ ├── root.go
│ │ ├── version.go
│ │ ├── wsl.go
│ │ ├── wsl_info.go
│ │ ├── wsl_integration_docker_linux.go
│ │ ├── wsl_integration_linux.go
│ │ └── wsl_integration_state_linux.go
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── main.go
│ │ ├── pkg
│ │ ├── certificates
│ │ │ ├── certificates_windows.go
│ │ │ └── certificates_windows_test.go
│ │ ├── dockerproxy
│ │ │ ├── defaults.go
│ │ │ ├── generate.go
│ │ │ ├── models
│ │ │ │ └── doc.go
│ │ │ ├── mungers
│ │ │ │ ├── containers_create_linux.go
│ │ │ │ ├── containers_create_linux_test.go
│ │ │ │ ├── containers_create_windows.go
│ │ │ │ ├── containers_create_windows_test.go
│ │ │ │ ├── doc.go
│ │ │ │ ├── helpers.go
│ │ │ │ └── helpers_linux.go
│ │ │ ├── platform
│ │ │ │ ├── hyperv.go
│ │ │ │ ├── hyperv_test.go
│ │ │ │ ├── serve_linux.go
│ │ │ │ ├── serve_windows.go
│ │ │ │ ├── serve_windows_test.go
│ │ │ │ ├── vsock_linux.go
│ │ │ │ └── wsl_mountpoint_linux.go
│ │ │ ├── serve.go
│ │ │ ├── start.go
│ │ │ ├── swagger-configuration.yaml
│ │ │ └── util
│ │ │ │ ├── pipe.go
│ │ │ │ ├── pipe_test.go
│ │ │ │ └── reverse_proxy.go
│ │ ├── integration
│ │ │ ├── docker_linux.go
│ │ │ ├── docker_linux_test.go
│ │ │ └── integration.go
│ │ ├── process
│ │ │ ├── imports_windows.go
│ │ │ ├── kill_others_linux.go
│ │ │ ├── kill_windows.go
│ │ │ ├── run_windows.go
│ │ │ └── wait_windows.go
│ │ ├── version
│ │ │ └── version.go
│ │ └── wsl-utils
│ │ │ ├── doc.go
│ │ │ ├── install_windows.go
│ │ │ ├── run_windows.go
│ │ │ ├── version_windows.go
│ │ │ └── version_windows_test.go
│ │ └── wix
│ │ ├── check_windows.go
│ │ ├── doc.go
│ │ ├── helpers_windows.go
│ │ ├── imports_windows.go
│ │ ├── install_windows.go
│ │ └── main_windows.go
└── sudo-prompt
│ ├── build-sudo-prompt
│ ├── sudo-prompt-script
│ └── sudo-prompt.applescript
├── tsconfig.json
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 | charset = utf-8
9 | end_of_line = lf
10 | indent_size = 2
11 | indent_style = space
12 | insert_final_newline = true
13 | quote_type = single
14 | trim_trailing_whitespace = true
15 |
16 | [*.go]
17 | indent_style = tab
18 |
19 | [*.{sh,bash,bats}]
20 | indent_size = 4
21 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # All Linux scripts should have LF line endings
2 | # But only text files should be changed (not any binaries / images / etc.)
3 | resources/linux/** text=auto eol=lf
4 | resources/setup-spin text=auto eol=lf
5 | pkg/rancher-desktop/assets/scripts/** text=auto eol=lf
6 |
--------------------------------------------------------------------------------
/.github/.yamlfmt:
--------------------------------------------------------------------------------
1 | formatter:
2 | indentless_arrays: true
3 | retain_line_breaks: true
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: true
2 | contact_links:
3 | - name: Ask a question (GitHub Discussions)
4 | url: https://github.com/rancher-sandbox/rancher-desktop/discussions
5 | about: We use GitHub Discussions for questions and GitHub issues for tracking bug reports and feature requests
6 | - name: Chat with Rancher Desktop users and developers
7 | url: https://slack.rancher.io/
8 | about: We hang out in the `#rancher-desktop` channel in the Rancher Users slack
9 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------
1 | name: Feature Request
2 | description: "Suggest a feature or idea to Rancher Desktop."
3 | labels: ["kind/enhancement"]
4 | body:
5 | - type: textarea
6 | attributes:
7 | label: Problem Description
8 | description: "A clear and concise description of what enhancement you'd like."
9 | validations:
10 | required: true
11 | - type: textarea
12 | attributes:
13 | label: Proposed Solution
14 | description: "Describe the solution you'd like in a clear and concise manner."
15 | validations:
16 | required: true
17 | - type: textarea
18 | attributes:
19 | label: Additional Information
20 | description: "Add any other context/information about the problem here."
21 | validations:
22 | required: false
23 |
--------------------------------------------------------------------------------
/.github/actions/spelling/allow.txt:
--------------------------------------------------------------------------------
1 | emoji
2 | github
3 | https
4 | passwordless
5 | ssh
6 | ubuntu
7 | workarounds
8 |
--------------------------------------------------------------------------------
/.github/actions/spelling/reject.txt:
--------------------------------------------------------------------------------
1 | ^attache$
2 | ^bellow$
3 | benefitting
4 | occurences?
5 | ^dependan.*
6 | ^oer$
7 | Sorce
8 | ^[Ss]pae.*
9 | ^untill$
10 | ^untilling$
11 | ^wether.*
12 |
--------------------------------------------------------------------------------
/.github/workflows/docker-cli-monitor.yaml:
--------------------------------------------------------------------------------
1 | name: Check for new releases of docker/cli
2 | on:
3 | schedule:
4 | - cron: '55 8 * * *'
5 | workflow_dispatch: {}
6 |
7 | jobs:
8 | check-for-token:
9 | outputs:
10 | has-token: ${{ steps.calc.outputs.HAS_SECRET }}
11 | runs-on: ubuntu-latest
12 | steps:
13 | - id: calc
14 | run: echo "HAS_SECRET=${HAS_SECRET}" >> "${GITHUB_OUTPUT}"
15 | env:
16 | HAS_SECRET: ${{ secrets.RUN_WORKFLOW_FROM_WORKFLOW != '' }}
17 |
18 | check-docker-cli:
19 | needs: check-for-token
20 | if: needs.check-for-token.outputs.has-token == 'true'
21 | runs-on: ubuntu-latest
22 | permissions:
23 | issues: write
24 | steps:
25 |
26 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
27 | with:
28 | fetch-depth: 0
29 |
30 | - uses: ./.github/actions/yarn-install
31 |
32 | - run: yarn dcmonitor
33 | env:
34 | GITHUB_CREATE_TOKEN: ${{ secrets.RUN_WORKFLOW_FROM_WORKFLOW }}
35 | GITHUB_TOKEN: ${{ github.token }}
36 |
--------------------------------------------------------------------------------
/.github/workflows/rddepman.yaml:
--------------------------------------------------------------------------------
1 | name: Update external dependencies
2 | on:
3 | schedule:
4 | - cron: '23 8 * * *'
5 | workflow_dispatch: {}
6 |
7 | permissions:
8 | contents: write
9 | pull-requests: write
10 |
11 | jobs:
12 | check-for-token:
13 | outputs:
14 | has-token: ${{ steps.calc.outputs.HAS_SECRET }}
15 | runs-on: ubuntu-latest
16 | steps:
17 | - id: calc
18 | run: echo "HAS_SECRET=${HAS_SECRET}" >> "${GITHUB_OUTPUT}"
19 | env:
20 | HAS_SECRET: ${{ secrets.RUN_WORKFLOW_FROM_WORKFLOW != '' }}
21 |
22 | check-update-versions:
23 | needs: check-for-token
24 | if: needs.check-for-token.outputs.has-token == 'true'
25 | runs-on: ubuntu-latest
26 | steps:
27 |
28 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
29 | with:
30 | fetch-depth: 0
31 |
32 | - uses: ./.github/actions/yarn-install
33 |
34 | - run: yarn rddepman
35 | env:
36 | GITHUB_TOKEN: ${{ secrets.RUN_WORKFLOW_FROM_WORKFLOW }}
37 |
--------------------------------------------------------------------------------
/.github/workflows/release-merge-to-main.yaml:
--------------------------------------------------------------------------------
1 | name: "Release: Merge to main"
2 |
3 | on:
4 | release:
5 | types:
6 | - created
7 | - published
8 | - released
9 |
10 | concurrency:
11 | group: ${{ github.workflow }}-${{ github.ref }}
12 | cancel-in-progress: true
13 |
14 | permissions: {}
15 |
16 | jobs:
17 | check-for-token:
18 | outputs:
19 | has-token: ${{ steps.calc.outputs.HAS_SECRET }}
20 | runs-on: ubuntu-latest
21 | steps:
22 | - id: calc
23 | run: echo "HAS_SECRET=${HAS_SECRET}" >> "${GITHUB_OUTPUT}"
24 | env:
25 | HAS_SECRET: ${{ secrets.RUN_WORKFLOW_FROM_WORKFLOW != '' }}
26 |
27 | create-pr:
28 | needs: check-for-token
29 | if: needs.check-for-token.outputs.has-token == 'true'
30 | runs-on: ubuntu-latest
31 | permissions:
32 | contents: write
33 | steps:
34 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
35 | - uses: ./.github/actions/yarn-install
36 | - run: node scripts/ts-wrapper.js scripts/release-merge-to-main.ts
37 | env:
38 | GITHUB_WRITE_TOKEN: ${{ github.token }}
39 | GITHUB_PR_TOKEN: ${{ secrets.RUN_WORKFLOW_FROM_WORKFLOW }}
40 |
--------------------------------------------------------------------------------
/.github/workflows/ucmonitor.yaml:
--------------------------------------------------------------------------------
1 | name: Check for unreleased changes
2 | on:
3 | schedule:
4 | - cron: '48 8 * * *'
5 | workflow_dispatch: {}
6 |
7 | permissions:
8 | issues: write
9 |
10 | jobs:
11 | check-for-token:
12 | outputs:
13 | has-token: ${{ steps.calc.outputs.HAS_SECRET }}
14 | runs-on: ubuntu-latest
15 | steps:
16 | - id: calc
17 | run: echo "HAS_SECRET=${HAS_SECRET}" >> "${GITHUB_OUTPUT}"
18 | env:
19 | HAS_SECRET: ${{ secrets.RUN_WORKFLOW_FROM_WORKFLOW != '' }}
20 |
21 | check-unreleased-changes:
22 | needs: check-for-token
23 | if: needs.check-for-token.outputs.has-token == 'true'
24 | runs-on: ubuntu-latest
25 | steps:
26 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
27 | with:
28 | fetch-depth: 0
29 |
30 | - uses: ./.github/actions/yarn-install
31 |
32 | - run: yarn ucmonitor
33 | env:
34 | GITHUB_TOKEN: ${{ secrets.RUN_WORKFLOW_FROM_WORKFLOW }}
35 |
--------------------------------------------------------------------------------
/.github/workflows/windows-e2e.yaml:
--------------------------------------------------------------------------------
1 | name: e2e tests on Windows
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches-ignore:
7 | - 'dependabot/**'
8 | pull_request: {}
9 |
10 | defaults:
11 | run:
12 | shell: powershell
13 | jobs:
14 | check-paths:
15 | uses: ./.github/workflows/paths-ignore.yaml
16 | e2e-tests:
17 | needs: check-paths
18 | if: needs.check-paths.outputs.should-run == 'true'
19 | timeout-minutes: 90
20 | runs-on: windows-latest
21 | steps:
22 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
23 | with:
24 | persist-credentials: false
25 | - uses: ./.github/actions/setup-environment
26 | - uses: ./.github/actions/yarn-install
27 | - name: Run e2e Tests
28 | run: yarn test:e2e
29 | env:
30 | RD_DEBUG_ENABLED: '1'
31 | - name: Upload failure reports
32 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
33 | if: always()
34 | with:
35 | name: e2etest-artifacts
36 | path: ./e2e/reports/*
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.exe
2 | /bats/bats.tar.gz
3 | /bats/bin/
4 | /bats/logs/
5 | /coverage/
6 | /dist/
7 | /e2e/reports/
8 | /go.work.sum
9 | /node_modules/
10 | /pkg/rancher-desktop/nuxt/
11 | /resources/cert-manager*
12 | /resources/darwin/
13 | /resources/host/
14 | /resources/linux/*
15 | !/resources/linux/rancher-desktop.desktop
16 | /resources/preload.js*
17 | /resources/rancher-dashboard/
18 | /resources/rdx-proxy.tar
19 | /resources/spin-operator*
20 | /resources/win32/
21 | /screenshots/output/
22 | /src/go/rdctl/pkg/options/generated/*.go
23 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "bats/bats-core"]
2 | path = bats/bats-core
3 | url = https://github.com/rancher-sandbox/bats-core.git
4 | branch = master
5 | [submodule "bats/bats-assert"]
6 | path = bats/bats-assert
7 | url = https://github.com/rancher-sandbox/bats-assert.git
8 | branch = master
9 | [submodule "bats/bats-support"]
10 | path = bats/bats-support
11 | url = https://github.com/rancher-sandbox/bats-support.git
12 | branch = master
13 | [submodule "bats/bats-file"]
14 | path = bats/bats-file
15 | url = https://github.com/rancher-sandbox/bats-file.git
16 | branch = master
17 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | const packageJson = require('./package.json');
2 |
3 | const electronVersion = parseInt(/\d+/.exec(packageJson.devDependencies.electron), 10);
4 |
5 | module.exports = {
6 | presets: [
7 | [
8 | '@vue/cli-plugin-babel/preset',
9 | { useBuiltIns: false },
10 | ],
11 | [
12 | '@babel/preset-env',
13 | {
14 | targets: {
15 | node: 'current',
16 | electron: electronVersion,
17 | },
18 | },
19 | ],
20 | ],
21 | env: {
22 | test: {
23 | presets: [
24 | ['@babel/env',
25 | { targets: { node: 'current' } },
26 | ],
27 | ],
28 | },
29 | },
30 | plugins: [
31 | '@babel/plugin-proposal-class-properties',
32 | '@babel/plugin-proposal-nullish-coalescing-operator',
33 | '@babel/plugin-proposal-optional-chaining',
34 | '@babel/plugin-proposal-private-methods',
35 | '@babel/plugin-proposal-private-property-in-object',
36 | ],
37 | };
38 |
--------------------------------------------------------------------------------
/bats/tests/compose/testdata/Dockerfile.nginx:
--------------------------------------------------------------------------------
1 | ARG IMAGE_NGINX
2 | FROM ${IMAGE_NGINX}
3 |
--------------------------------------------------------------------------------
/bats/tests/compose/testdata/app/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG IMAGE_PYTHON=python:3.9-slim
2 | FROM ${IMAGE_PYTHON}
3 |
4 | WORKDIR /app
5 |
6 | COPY requirements.txt .
7 | RUN pip install --no-cache-dir -r requirements.txt
8 |
9 | COPY . .
10 |
11 | CMD ["python", "app.py"]
12 |
--------------------------------------------------------------------------------
/bats/tests/compose/testdata/app/app.py:
--------------------------------------------------------------------------------
1 | from flask import Flask
2 | app = Flask(__name__)
3 |
4 | @app.route('/')
5 | def hello():
6 | return "Hello World!"
7 |
8 | if __name__ == '__main__':
9 | app.run(host='0.0.0.0', port=8000)
10 |
--------------------------------------------------------------------------------
/bats/tests/compose/testdata/app/requirements.txt:
--------------------------------------------------------------------------------
1 | flask
2 |
--------------------------------------------------------------------------------
/bats/tests/compose/testdata/compose.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | nginx:
3 | container_name: nginx
4 | build:
5 | args:
6 | - IMAGE_NGINX
7 | dockerfile: Dockerfile.nginx
8 | volumes:
9 | - ./nginx.conf:/etc/nginx/nginx.conf
10 | ports:
11 | - '127.0.0.1:8080:80'
12 | web:
13 | build:
14 | args:
15 | - IMAGE_PYTHON
16 | context: app
17 | # flask requires SIGINT to stop gracefully
18 | # (default stop signal from Compose is SIGTERM)
19 | stop_signal: SIGINT
20 | ports:
21 | - '8000:8000'
22 |
--------------------------------------------------------------------------------
/bats/tests/compose/testdata/nginx.conf:
--------------------------------------------------------------------------------
1 | worker_processes 1;
2 |
3 | error_log stderr info;
4 |
5 | events {
6 | worker_connections 1024;
7 | }
8 |
9 | http {
10 | include mime.types;
11 | sendfile on;
12 | proxy_read_timeout 5s;
13 |
14 | server {
15 | listen 80;
16 | server_name localhost;
17 |
18 | # Serve the default nginx welcome page
19 | location / {
20 | root /usr/share/nginx/html;
21 | index index.html;
22 | }
23 |
24 | # Proxy requests to /app to the backend service
25 | location /app {
26 | proxy_pass http://host.docker.internal:8000/;
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/bats/tests/containers/catch-duplicate-api-patterns.bats:
--------------------------------------------------------------------------------
1 | load '../helpers/load'
2 | RD_USE_IMAGE_ALLOW_LIST=true
3 |
4 | @test 'catch attempts to add duplicate patterns via the API with enabled on' {
5 | factory_reset
6 | start_kubernetes
7 | wait_for_kubelet
8 | wait_for_container_engine
9 |
10 | run update_allowed_patterns true "$IMAGE_NGINX" "$IMAGE_BUSYBOX" "$IMAGE_RUBY" "$IMAGE_BUSYBOX"
11 | assert_failure
12 | assert_output --partial $"field \"containerEngine.allowedImages.patterns\" has duplicate entries: \"$IMAGE_BUSYBOX\""
13 | }
14 |
15 | @test 'catch attempts to add duplicate patterns via the API with enabled off' {
16 | run update_allowed_patterns false "$IMAGE_NGINX" "$IMAGE_BUSYBOX" "$IMAGE_RUBY" "$IMAGE_BUSYBOX"
17 | assert_failure
18 | assert_output --partial $"field \"containerEngine.allowedImages.patterns\" has duplicate entries: \"$IMAGE_BUSYBOX\""
19 | }
20 |
--------------------------------------------------------------------------------
/bats/tests/containers/factory-reset-containerd-shims.bats:
--------------------------------------------------------------------------------
1 | load '../helpers/load'
2 |
3 | BOGUS_SHIM="${PATH_CONTAINERD_SHIMS}/containerd-shim-bogus-v1"
4 |
5 | local_setup_file() {
6 | RD_USE_RAMDISK=false # interferes with deleting $PATH_APP_HOME
7 |
8 | delete_all_snapshots
9 | rm -rf "$PATH_CONTAINERD_SHIMS"
10 | }
11 |
12 | local_teardown_file() {
13 | rm -rf "$PATH_CONTAINERD_SHIMS"
14 | }
15 |
16 | @test 'factory reset' {
17 | # On Windows the cache directory is under PATH_APP_HOME.
18 | factory_reset --remove-kubernetes-cache=true
19 | assert_not_exists "$PATH_APP_HOME"
20 | }
21 |
22 | @test 'factory reset will not remove any shims' {
23 | assert_not_exists "$PATH_CONTAINERD_SHIMS"
24 | create_file "$BOGUS_SHIM" <<<''
25 | factory_reset
26 | assert_exists "$BOGUS_SHIM"
27 | assert_exists "$PATH_APP_HOME"
28 | }
29 |
30 | @test 'factory reset will remove empty shim directory' {
31 | rm "$BOGUS_SHIM"
32 | factory_reset
33 | assert_not_exists "$PATH_CONTAINERD_SHIMS"
34 | assert_not_exists "$PATH_APP_HOME"
35 | }
36 |
--------------------------------------------------------------------------------
/bats/tests/containers/factory-reset-snapshots.bats:
--------------------------------------------------------------------------------
1 | load '../helpers/load'
2 |
3 | local_setup_file() {
4 | RD_USE_RAMDISK=false # interferes with deleting $PATH_APP_HOME
5 | }
6 |
7 | @test 'factory reset' {
8 | delete_all_snapshots
9 | rm -rf "$PATH_CONTAINERD_SHIMS"
10 | # On Windows the cache directory is under PATH_APP_HOME.
11 | factory_reset --remove-kubernetes-cache=true
12 | }
13 |
14 | @test 'Start up Rancher Desktop with a snapshots subdirectory' {
15 | start_container_engine
16 | wait_for_container_engine
17 | wait_for_backend
18 | }
19 |
20 | @test "Verify the snapshot dir isn't deleted on factory-reset" {
21 | rdctl shutdown
22 | rdctl snapshot create shortlived-snapshot
23 | factory_reset --remove-kubernetes-cache=true
24 | assert_not_exists "$PATH_APP_HOME/rd-engine.json"
25 | assert_exists "$PATH_SNAPSHOTS"
26 | run ls -A "$PATH_SNAPSHOTS"
27 | assert_output
28 | }
29 |
30 | @test 'Verify factory-reset deletes an empty snapshots directory' {
31 | rdctl snapshot delete shortlived-snapshot
32 | factory_reset --remove-kubernetes-cache=true
33 | assert_not_exists "$PATH_APP_HOME"
34 | }
35 |
--------------------------------------------------------------------------------
/bats/tests/containers/host-connectivity.bats:
--------------------------------------------------------------------------------
1 | # bats file_tags=opensuse
2 |
3 | load '../helpers/load'
4 |
5 | @test 'factory reset' {
6 | factory_reset
7 | }
8 |
9 | @test 'start container engine' {
10 | start_container_engine
11 | wait_for_container_engine
12 | }
13 |
14 | verify_host_connectivity() {
15 | run ctrctl run --rm "$IMAGE_BUSYBOX" timeout -s INT 10 ping -c 5 "$1"
16 | assert_success
17 | assert_output --partial "5 packets transmitted, 5 packets received, 0% packet loss"
18 | }
19 |
20 | @test 'ping host.docker.internal from a container' {
21 | verify_host_connectivity "host.docker.internal"
22 | }
23 |
24 | @test 'ping host.rancher-desktop.internal from a container' {
25 | verify_host_connectivity "host.rancher-desktop.internal"
26 | }
27 |
--------------------------------------------------------------------------------
/bats/tests/containers/init.bats:
--------------------------------------------------------------------------------
1 | # verify that running a container with --init is working
2 | # bats file_tags=opensuse
3 |
4 | load '../helpers/load'
5 |
6 | @test 'factory reset' {
7 | factory_reset
8 | }
9 |
10 | @test 'start container engine' {
11 | start_container_engine
12 | wait_for_container_engine
13 | }
14 |
15 | @test 'run container with init process' {
16 | # BUG BUG BUG
17 | # The following `ctrctl run` command includes the `-i` option to work around a docker
18 | # bug on Windows: https://github.com/rancher-sandbox/rancher-desktop/issues/3239
19 | # It is harmless in other configurations, but should not be required here.
20 | # BUG BUG BUG
21 | run ctrctl run -i --rm --init "$IMAGE_BUSYBOX" ps -ef
22 | assert_success
23 | # PID USER TIME COMMAND
24 | # 1 root 0:00 /sbin/docker-init -- ps -ef
25 | # 1 root 0:00 /sbin/tini -- ps -ef
26 | assert_line --regexp '^ +1 .+ /sbin/(docker-init|tini) -- ps -ef$'
27 | }
28 |
--------------------------------------------------------------------------------
/bats/tests/containers/run-rancher.bats:
--------------------------------------------------------------------------------
1 | # bats file_tags=opensuse
2 |
3 | load '../helpers/load'
4 | RD_FILE_RAMDISK_SIZE=12 # We need more disk to run the Rancher image.
5 |
6 | @test 'factory reset' {
7 | factory_reset
8 | }
9 |
10 | @test 'start container engine' {
11 | start_container_engine
12 | wait_for_container_engine
13 | }
14 |
15 | @test 'run rancher' {
16 | local rancher_image
17 | rancher_image="rancher/rancher:$(rancher_image_tag)"
18 |
19 | ctrctl pull "$rancher_image"
20 | ctrctl run --privileged -d --restart=no -p 8080:80 -p 8443:443 --name rancher "$rancher_image"
21 | }
22 |
23 | @test 'verify rancher' {
24 | local max_tries=9
25 | if [[ -n ${CI:-} ]]; then
26 | max_tries=30
27 | fi
28 | run try --max $max_tries --delay 10 curl --insecure --silent --show-error "https://localhost:8443/dashboard/auth/login"
29 | assert_success
30 | assert_output --partial "Rancher Dashboard"
31 | run ctrctl logs rancher
32 | assert_success
33 | assert_output --partial "Bootstrap Password:"
34 | }
35 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM registry.opensuse.org/opensuse/bci/golang:stable AS builder
2 | WORKDIR /usr/src/app
3 | COPY bin/dummy.go .
4 | ENV GOOS=windows
5 | RUN go build -o /dummy.exe -ldflags '-s -w' dummy.go
6 |
7 | FROM registry.opensuse.org/opensuse/bci/golang:stable AS server-builder
8 | WORKDIR /usr/src/app
9 | COPY bin/server.go .
10 | ENV GOOS=linux
11 | RUN go build -o /server -ldflags '-s -w' server.go
12 |
13 | FROM registry.opensuse.org/opensuse/bci/bci-minimal
14 | ARG variant=basic
15 |
16 | ADD ${variant}.json /metadata.json
17 | ADD extension-icon.svg /extension-icon.svg
18 | ADD ui /ui/
19 | ADD bin /bin/
20 | COPY --from=builder /dummy.exe /bin/
21 | COPY --from=server-builder /server /bin/
22 | ADD compose.yaml /compose/
23 | RUN ln -s does/not/exist /compose/dangling-link
24 | RUN ln -s compose.yaml /compose/link
25 |
26 | ENTRYPOINT ["/bin/server"]
27 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/Makefile:
--------------------------------------------------------------------------------
1 | all: \
2 | image-basic image-missing-icon image-ui \
3 | image-vm-image image-vm-compose image-host-binaries image-host-apis
4 |
5 | TOOL ?= docker
6 | NAMESPACE := $(if $(filter %nerdctl,${TOOL}),--namespace=rancher-desktop-extensions)
7 |
8 | NAMESPACE = $(if $(filter %nerdctl,${TOOL}),--namespace=rancher-desktop-extensions)
9 |
10 | image-%:
11 | ${TOOL} ${NAMESPACE} build -t rd/extension/$(@:image-%=%) --build-arg variant=$(@:image-%=%) .
12 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/README.md:
--------------------------------------------------------------------------------
1 | This directory contains sample docker extensions.
2 |
3 | ### basic
4 | A basic extension, containing the bare minimum (just an icon).
5 |
6 | ### missing-icon
7 | As above, but even the icon is missing.
8 |
9 | ### missing-icon-file
10 | Like the basic extension, but the icon file specified does not exist.
11 |
12 | ### ui
13 | Presents basic UI. We do not yet test interaction with UI.
14 |
15 | ### vm-image
16 | Contains a docker image to run.
17 |
18 | ### vm-compose
19 | Contains a docker compose file to run. (Not supported.)
20 |
21 | ### host-binaries
22 | Contains binaries to be copied to the host.
23 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/basic.json:
--------------------------------------------------------------------------------
1 | {
2 | "icon": "extension-icon.svg"
3 | }
4 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/bin/dummy.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "log"
6 | "os"
7 | "os/exec"
8 | )
9 |
10 | func main() {
11 | ctx := context.Background()
12 | cmd := exec.CommandContext(ctx, os.Args[1], os.Args[2:]...)
13 | cmd.Stdin = os.Stdin
14 | cmd.Stdout = os.Stdout
15 | cmd.Stderr = os.Stderr
16 | err := cmd.Run()
17 | if exitError, ok := err.(*exec.ExitError); ok {
18 | if exitError.ExitCode() > -1 {
19 | os.Exit(exitError.ExitCode())
20 | }
21 | }
22 | if err != nil {
23 | log.Fatal(err)
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/bin/dummy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | exec "$@"
4 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/compose.yaml:
--------------------------------------------------------------------------------
1 | name: sample-compose
2 | services:
3 | backend-service:
4 | image: "${DESKTOP_PLUGIN_IMAGE}"
5 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/everything.json:
--------------------------------------------------------------------------------
1 | {
2 | "icon": "extension-icon.svg",
3 | "host": {
4 | "binaries": [
5 | {
6 | "darwin": [
7 | {
8 | "path": "/bin/dummy.sh"
9 | }
10 | ],
11 | "windows": [
12 | {
13 | "path": "/bin/dummy.exe"
14 | }
15 | ],
16 | "linux": [
17 | {
18 | "path": "/bin/dummy.sh"
19 | }
20 | ]
21 | }
22 | ]
23 | },
24 | "ui": {
25 | "dashboard-tab": {
26 | "title": "Sample Extension With Everything",
27 | "root": "/ui",
28 | "src": "index.html",
29 | "backend": {
30 | "socket": "hello.sock"
31 | }
32 | }
33 | },
34 | "vm": {
35 | "composefile": "/compose/compose.yaml",
36 | "exposes": {
37 | "socket": "hello.sock"
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/extension-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/host-apis.json:
--------------------------------------------------------------------------------
1 | {
2 | "info": "This is used to do manual testing of various host APIs",
3 | "icon": "extension-icon.svg",
4 | "ui": {
5 | "dashboard-tab": {
6 | "title": "RDX Host-APIs Test",
7 | "root": "/ui",
8 | "src": "host-apis.html"
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/host-binaries.json:
--------------------------------------------------------------------------------
1 | {
2 | "icon": "extension-icon.svg",
3 | "host": {
4 | "binaries": [
5 | {
6 | "darwin": [
7 | {
8 | "path": "/bin/dummy.sh"
9 | }
10 | ],
11 | "windows": [
12 | {
13 | "path": "/bin/dummy.exe"
14 | }
15 | ],
16 | "linux": [
17 | {
18 | "path": "/bin/dummy.sh"
19 | }
20 | ]
21 | }
22 | ]
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/missing-icon-file.json:
--------------------------------------------------------------------------------
1 | {
2 | "icon": "does-not-exist.svg",
3 | "info": "This extension uses an icon that does not exist."
4 | }
5 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/missing-icon.json:
--------------------------------------------------------------------------------
1 | {
2 | "info": "This extension definition is missing an icon."
3 | }
4 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/ui.json:
--------------------------------------------------------------------------------
1 | {
2 | "icon": "extension-icon.svg",
3 | "ui": {
4 | "dashboard-tab": {
5 | "title": "Sample Extension",
6 | "root": "/ui",
7 | "src": "index.html"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/ui/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Test Extension
5 |
6 |
7 | Test Extension
8 | This is a test extension.
9 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/vm-compose.json:
--------------------------------------------------------------------------------
1 | {
2 | "icon": "extension-icon.svg",
3 | "info": "This image uses vm.composefile",
4 | "vm": {
5 | "composefile": "/compose/compose.yaml"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/bats/tests/extensions/testdata/vm-image.json:
--------------------------------------------------------------------------------
1 | {
2 | "icon": "extension-icon.svg",
3 | "info": "This extension contains a reference to an image.",
4 | "vm": {
5 | "image": "rd/extension/vm-image"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/bats/tests/helpers/kubernetes.bats:
--------------------------------------------------------------------------------
1 | load '../helpers/load'
2 |
3 | : "${RD_INFO:=false}"
4 |
5 | @test 'unwrap_kube_list: no list' {
6 | run echo '{"kind": "Pod"}'
7 | assert_success
8 |
9 | run unwrap_kube_list
10 | assert_success
11 |
12 | run jq_output .kind
13 | assert_success
14 | assert_output Pod
15 | }
16 |
17 | @test 'unwrap_kube_list: no items' {
18 | run echo '{"kind": "List"}'
19 | assert_success
20 |
21 | run unwrap_kube_list
22 | assert_failure
23 | }
24 |
25 | @test 'unwrap_kube_list: one item' {
26 | run echo '{"kind": "List", "items": [{"kind": "Pod"}]}'
27 | assert_success
28 |
29 | run unwrap_kube_list
30 | assert_success
31 |
32 | run jq_output .kind
33 | assert_success
34 | assert_output Pod
35 | }
36 |
37 | @test 'unwrap_kube_list: two items' {
38 | run echo '{"kind": "List", "items": [{"kind": "Pod"},{"kind": "Pod"}]}'
39 | assert_success
40 |
41 | run unwrap_kube_list
42 | assert_failure
43 | }
44 |
45 | @test 'unwrap_kube_list: not JSON' {
46 | run echo 'Some random error message'
47 | assert_success
48 |
49 | run unwrap_kube_list
50 | assert_failure
51 | }
52 |
--------------------------------------------------------------------------------
/bats/tests/helpers/snapshots.bash:
--------------------------------------------------------------------------------
1 | delete_all_snapshots() {
2 | run rdctl snapshot list --json
3 | assert_success
4 | # On Windows, executing native Windows executables consumes stdin.
5 | # https://github.com/microsoft/WSL/issues/10429
6 | # Work around the issue by using `run` to populate `${lines[@]}` ahead of
7 | # time, so that we don't need the buffer during the loop.
8 | run jq_output .name
9 | assert_success
10 | local name
11 | for name in "${lines[@]}"; do
12 | rdctl snapshot delete "$name"
13 | done
14 | run rdctl snapshot list
15 | assert_success
16 | assert_output --partial 'No snapshots'
17 | }
18 |
--------------------------------------------------------------------------------
/bats/tests/k8s/enable-disable-k8s.bats:
--------------------------------------------------------------------------------
1 | # Test case 8, 13, 22
2 |
3 | load '../helpers/load'
4 |
5 | @test 'factory reset' {
6 | factory_reset
7 | }
8 |
9 | verify_k8s_is_running() {
10 | wait_for_container_engine
11 | wait_for_service_status k3s started
12 | }
13 |
14 | @test 'start rancher desktop with kubernetes enabled' {
15 | start_kubernetes
16 | wait_for_kubelet
17 | verify_k8s_is_running
18 | }
19 |
20 | @test 'disable kubernetes' {
21 | rdctl set --kubernetes.enabled=false
22 | wait_for_container_engine
23 | wait_for_service_status k3s stopped
24 | }
25 |
26 | @test 're-enable kubernetes' {
27 | rdctl set --kubernetes.enabled=true
28 | wait_for_kubelet
29 | verify_k8s_is_running
30 | }
31 |
--------------------------------------------------------------------------------
/bats/tests/k8s/foreach-k3s-version.bats:
--------------------------------------------------------------------------------
1 | load '../helpers/load'
2 |
3 | wait_for_dns() {
4 | try assert_pod_containers_are_running \
5 | --namespace kube-system \
6 | --selector k8s-app=kube-dns
7 | }
8 |
9 | foreach_k3s_version \
10 | factory_reset \
11 | start_kubernetes \
12 | wait_for_kubelet \
13 | wait_for_dns
14 |
--------------------------------------------------------------------------------
/bats/tests/k8s/specify-invalid-k8s-version.bats:
--------------------------------------------------------------------------------
1 | load '../helpers/load'
2 |
3 | @test 'factory reset' {
4 | factory_reset
5 | }
6 |
7 | @test 'invalid k8s version' {
8 | start_kubernetes --kubernetes.version=moose
9 | wait_for_container_engine
10 | # Can't use wait_for_api_server because it hard-wires a valid k8s version and we're specifying an invalid one here.
11 | # and we're specifying an invalid one here
12 | local timeout="$(($(date +%s) + 10 * 60))"
13 | until kubectl get --raw /readyz &>/dev/null; do
14 | assert [ "$(date +%s)" -lt "$timeout" ]
15 | sleep 1
16 | done
17 | # No way there's a race-condition here.
18 | # The version was checked and written to the log file before starting k8s,
19 | # and we have to wait a few minutes before k8s is ready and we're at the next line.
20 | assert_file_contains "$PATH_LOGS/kube.log" "Requested kubernetes version 'moose' is not a supported version. Falling back to"
21 | }
22 |
23 | # on macOS it still hangs without this
24 | @test 'shutdown' {
25 | if is_macos; then
26 | rdctl shutdown
27 | fi
28 | }
29 |
--------------------------------------------------------------------------------
/bats/tests/profile/wasm.bats:
--------------------------------------------------------------------------------
1 | load '../helpers/load'
2 |
3 | local_teardown_file() {
4 | foreach_profile delete_profile
5 | }
6 |
7 | @test 'create version 10 locked profile' {
8 | PROFILE_TYPE=$PROFILE_LOCKED
9 | create_profile
10 | add_profile_int version 10
11 | }
12 |
13 | @test 'start application' {
14 | factory_reset
15 | start_container_engine
16 | wait_for_container_engine
17 | }
18 |
19 | @test 'WASM mode should be locked down' {
20 | run rdctl set --experimental.container-engine.web-assembly.enabled
21 | assert_failure
22 | assert_output --partial 'field "experimental.containerEngine.webAssembly.enabled" is locked'
23 | }
24 |
25 | @test 'update locked profile to version 11' {
26 | PROFILE_TYPE=$PROFILE_LOCKED
27 | add_profile_int version 11
28 | }
29 |
30 | @test 'restart application with version 11 locked profile' {
31 | factory_reset
32 | start_container_engine
33 | wait_for_backend
34 | }
35 |
36 | @test 'WASM mode is now unlocked' {
37 | run rdctl set --experimental.container-engine.web-assembly.enabled
38 | assert_success
39 | assert_output --partial 'reconfiguring Rancher Desktop to apply changes'
40 | }
41 |
--------------------------------------------------------------------------------
/bats/tests/snapshots/test_rdctl_snapshot.bats:
--------------------------------------------------------------------------------
1 | load '../helpers/load'
2 |
3 | # TODO: Uncomment this test when snapshots go unhidden.
4 | #@test 'snapshot shows up in general help' {
5 | # run rdctl --help
6 | # assert_success
7 | # assert_output -partial snapshot
8 | #}
9 |
10 | @test 'complain about missing argument' {
11 | # These test the rdctl cmd layer, can't be easily unit-tested
12 | for arg in create restore delete; do
13 | run rdctl snapshot "$arg"
14 | assert_failure
15 | done
16 | }
17 |
--------------------------------------------------------------------------------
/build/signing-config-win.yaml:
--------------------------------------------------------------------------------
1 | # This file describes the code signing configuration for Windows.
2 |
3 | # The key is a directory name, relative to the unpacked zip file.
4 | # The value is an array of files in that directory to sign, or an explicit
5 | # negation (prefixed with "!"). Any files not listed is an error.
6 | .:
7 | - Rancher Desktop.exe
8 | - wix-custom-action.dll
9 | - '!d3dcompiler_47.dll' # spellcheck-ignore-line
10 | - '!ffmpeg.dll'
11 | - '!libEGL.dll' # spellcheck-ignore-line
12 | - '!libGLESv2.dll' # spellcheck-ignore-line
13 | - '!vk_swiftshader.dll' # spellcheck-ignore-line
14 | - '!vulkan-1.dll' # spellcheck-ignore-line
15 | resources/resources/win32/bin:
16 | - docker.exe
17 | - docker-credential-none.exe
18 | - nerdctl.exe
19 | - rdctl.exe
20 | - spin.exe
21 | - '!docker-credential-ecr-login.exe'
22 | - '!docker-credential-wincred.exe'
23 | - '!helm.exe'
24 | - '!kubectl.exe'
25 | - '!kuberlr.exe'
26 | resources/resources/win32/docker-cli-plugins:
27 | - '!docker-buildx.exe'
28 | - '!docker-compose.exe'
29 | resources/resources/win32/internal:
30 | - host-switch.exe
31 | - steve.exe
32 | - wsl-helper.exe
33 | - '!spin.exe'
34 |
--------------------------------------------------------------------------------
/build/wix/bannrbmp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/build/wix/bannrbmp.png
--------------------------------------------------------------------------------
/build/wix/dlgbmp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/build/wix/dlgbmp.png
--------------------------------------------------------------------------------
/dev-app-update.yml:
--------------------------------------------------------------------------------
1 | owner: rancher-sandbox
2 | repo: rancher-desktop
3 | updaterCacheDirName: rancher-desktop
4 | provider: custom
5 | upgradeServer: https://desktop.version.rancher.io/v1/checkupgrade
6 | vPrefixedTagName: true
7 |
--------------------------------------------------------------------------------
/docs/assets/images/contributing/e2e-failure-reports.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/docs/assets/images/contributing/e2e-failure-reports.png
--------------------------------------------------------------------------------
/docs/assets/images/contributing/e2e-summary.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/docs/assets/images/contributing/e2e-summary.png
--------------------------------------------------------------------------------
/docs/development/README.md:
--------------------------------------------------------------------------------
1 | # Developer Documentation
2 |
3 | Note that the below table of contents may be out of date
4 | (we may forget to update it). If you don't find what you need,
5 | ask around!
6 |
7 | [Information About Factory Reset](factory-reset.md)
8 | [Feature Tracker](features.md)
9 | [Tips for Working with OBS](obs.md)
10 | [Linux Release Process](linux-release-process.md)
11 | [Release Checklist](release-checklist.md)
12 | [Signing Rancher Desktop Releases](signing.md)
13 | [Generating Screenshots for User Documentation](../../screenshots/README.md)
14 | [Information on how to setup and run BATS tests](../../bats/README.md)
15 |
--------------------------------------------------------------------------------
/docs/development/env.md:
--------------------------------------------------------------------------------
1 | # Internal Rancher Desktop environment variables
2 |
3 | These variables are used for build and development purposes; they are not meant to be set by users.
4 |
5 | They do not form an API and may be changed or removed at any time without prior notice.
6 |
7 | ## RD_DEBUG_ENABLED=anything
8 |
9 | Forces debug logging to always be enabled. Useful to debug first-run issues when there is no `settings.yaml` yet to set debug mode.
10 |
11 | ## RD_FORCE_UPDATES_ENABLED=anything
12 |
13 | When set, it will force auto-update to be enabled even in `yarn dev` mode. Updates will be checked and downloaded, but **not** installed.
14 |
15 | ## RD_MOCK_MACOS_VERSION=semver
16 |
17 | Used for testing compatibility of the app with the OS version, for upgrade responder tests, and for enabling/disabling certain parts of the preferences (related to VZ emulation mode).
18 |
19 | ## RD_UPGRADE_RESPONDER_URL=http://localhost:8314/v1/checkupgrade
20 |
21 | Set an alternate upgrade responder endpoint for testing.
22 |
--------------------------------------------------------------------------------
/docs/development/factory-reset.md:
--------------------------------------------------------------------------------
1 | When `rdctl factory-reset` is launched from the UI, it writes its stdout into
2 | `TMP/rdctl-stdout.txt`
3 |
4 | where on linux `TMP` is usually `/tmp`,
5 |
6 | on macOS it's given by `$TMPDIR`
7 |
8 | and on Windows by `%TEMP%`(command shell) or `$env:TEMP`(powershell).
9 |
10 |
11 | This is most useful during development. When the UI runs in debug mode, it spawns `rdctl factory-reset` with the `--verbose` option.
12 |
13 | We can't write the output into the `logs` directory as `factory-reset` deletes it.
14 |
--------------------------------------------------------------------------------
/e2e/assets/k8s-deploy-sample/nginx-sample-app.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: nginx-app
5 | spec:
6 | selector:
7 | matchLabels:
8 | app: nginx
9 | version: v1
10 | replicas: 1
11 | template:
12 | metadata:
13 | labels:
14 | app: nginx
15 | version: v1
16 | spec:
17 | containers:
18 | - name: nginx
19 | image: nginx:latest
20 | ports:
21 | - containerPort: 80
22 | ---
23 | apiVersion: v1
24 | kind: Service
25 | metadata:
26 | name: nginx-app
27 | labels:
28 | app: nginx
29 | spec:
30 | type: NodePort
31 | ports:
32 | - port: 80
33 | name: http
34 | selector:
35 | app: nginx
36 |
--------------------------------------------------------------------------------
/e2e/config/playwright-config.ts:
--------------------------------------------------------------------------------
1 | import * as path from 'path';
2 |
3 | import type { Config, PlaywrightTestOptions } from '@playwright/test';
4 |
5 | const outputDir = path.join(__dirname, '..', 'e2e', 'test-results');
6 | const testDir = path.join(__dirname, '..', '..', 'e2e');
7 | // The provisioned github runners are much slower overall than cirrus's, so allow 2 hours for a full e2e run
8 | const timeScale = process.env.CI ? 4 : 1;
9 |
10 | const config: Config = {
11 | testDir,
12 | outputDir,
13 | timeout: 10 * 60 * 1000 * timeScale,
14 | globalTimeout: 30 * 60 * 1000 * timeScale,
15 | workers: 1,
16 | reporter: 'list',
17 | };
18 |
19 | export default config;
20 |
--------------------------------------------------------------------------------
/e2e/pages/containers-page.ts:
--------------------------------------------------------------------------------
1 | import { Page } from '@playwright/test';
2 |
3 | export class ContainersPage {
4 | readonly page: Page;
5 |
6 | constructor(page: Page) {
7 | this.page = page;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/e2e/pages/diagnostics-page.ts:
--------------------------------------------------------------------------------
1 | import type { Page, Locator } from '@playwright/test';
2 |
3 | interface CheckerRows {
4 | muteButton: Locator;
5 | }
6 |
7 | export class DiagnosticsPage {
8 | readonly page: Page;
9 | readonly diagnostics: Locator;
10 |
11 | constructor(page: Page) {
12 | this.page = page;
13 | this.diagnostics = page.locator('[data-test="diagnostics"]');
14 | }
15 |
16 | checkerRows(id: string): CheckerRows {
17 | return { muteButton: this.page.locator(`[data-test="diagnostics-mute-row-${ id }"]`) };
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/e2e/pages/extensions-page.ts:
--------------------------------------------------------------------------------
1 | import type { Page, Locator } from '@playwright/test';
2 |
3 | export class ExtensionsPage {
4 | readonly page: Page;
5 | readonly cardEpinio: Locator;
6 | readonly buttonInstall: Locator;
7 | readonly tabInstalled: Locator;
8 | readonly tabCatalog: Locator;
9 | readonly navEpinio: Locator;
10 |
11 | constructor(page: Page) {
12 | this.page = page;
13 | this.cardEpinio = page.locator('[data-test="extension-card-epinio"]');
14 | this.buttonInstall = page.locator('[data-test="button-install"]');
15 | this.tabInstalled = page.locator('.tab >> text=Installed');
16 | this.tabCatalog = page.locator('.tab >> text=Catalog');
17 | this.navEpinio = page.locator('[data-test="extension-nav-epinio"]');
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/e2e/pages/images-page.ts:
--------------------------------------------------------------------------------
1 | import type { Page, Locator } from '@playwright/test';
2 |
3 | export class ImagesPage {
4 | readonly page: Page;
5 | readonly fixedHeader: Locator;
6 | readonly table: Locator;
7 | readonly rows: Locator;
8 |
9 | constructor(page: Page) {
10 | this.page = page;
11 | this.fixedHeader = page.locator('.fixed-header-actions');
12 | this.table = page.locator('[data-test="imagesTable"]');
13 | this.rows = page.locator('[data-test="imagesTableRows"]');
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/e2e/pages/k8s-page.ts:
--------------------------------------------------------------------------------
1 | import type { Page, Locator } from '@playwright/test';
2 | export class K8sPage {
3 | readonly page: Page;
4 | readonly engineRuntime: Locator;
5 | readonly memorySlider: Locator;
6 | readonly resetButton: Locator;
7 | readonly cpuSlider: Locator;
8 | readonly port: Locator;
9 | readonly enableKubernetes: Locator;
10 |
11 | constructor(page: Page) {
12 | this.page = page;
13 | this.memorySlider = page.locator('[id="memoryInGBWrapper"]');
14 | this.resetButton = page.locator('[data-test="k8sResetBtn"]');
15 | this.cpuSlider = page.locator('[id="numCPUWrapper"]');
16 | this.engineRuntime = page.locator('.engine-selector');
17 | this.port = page.locator('[data-test="portConfig"]');
18 | this.enableKubernetes = page.locator('[data-test="enableKubernetes"]');
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/e2e/pages/portforward-page.ts:
--------------------------------------------------------------------------------
1 | import type { Page, Locator } from '@playwright/test';
2 | export class PortForwardPage {
3 | readonly page: Page;
4 | readonly fixedHeader: Locator;
5 | readonly content: Locator;
6 | readonly table: Locator;
7 |
8 | constructor(page: Page) {
9 | this.page = page;
10 | this.fixedHeader = page.locator('.fixed-header-actions');
11 | this.table = page.locator('.sortable-table-header');
12 | this.content = page.locator('.content');
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/e2e/pages/preferences/containerEngine.ts:
--------------------------------------------------------------------------------
1 | import type { Page, Locator } from '@playwright/test';
2 |
3 | export class ContainerEngineNav {
4 | readonly page: Page;
5 | readonly nav: Locator;
6 | readonly tabGeneral: Locator;
7 | readonly tabAllowedImages: Locator;
8 | readonly containerEngine: Locator;
9 | readonly allowedImages: Locator;
10 | readonly allowedImagesCheckbox: Locator;
11 | readonly enabledLockedField: Locator;
12 |
13 | constructor(page: Page) {
14 | this.page = page;
15 | this.nav = page.locator('[data-test="nav-container-engine"]');
16 | this.tabGeneral = page.locator('.tab >> text=General');
17 | this.tabAllowedImages = page.locator('.tab >> text=Allowed Images');
18 | this.containerEngine = page.locator('[data-test="containerEngine"]');
19 | this.allowedImages = page.locator('[data-test="allowedImages"]');
20 | this.allowedImagesCheckbox = page.getByTestId('allowedImagesCheckbox');
21 | this.enabledLockedField = this.allowedImagesCheckbox.locator('.icon-lock');
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/e2e/pages/preferences/index.ts:
--------------------------------------------------------------------------------
1 | import { ApplicationNav } from './application';
2 | import { ContainerEngineNav } from './containerEngine';
3 | import { KubernetesNav } from './kubernetes';
4 | import { VirtualMachineNav } from './virtualMachine';
5 | import { WslNav } from './wsl';
6 |
7 | import type { Page } from '@playwright/test';
8 |
9 | export class PreferencesPage {
10 | readonly page: Page;
11 | readonly application: ApplicationNav;
12 | readonly virtualMachine: VirtualMachineNav;
13 | readonly containerEngine: ContainerEngineNav;
14 | readonly kubernetes: KubernetesNav;
15 | readonly wsl: WslNav;
16 |
17 | constructor(page: Page) {
18 | this.page = page;
19 | this.application = new ApplicationNav(page);
20 | this.virtualMachine = new VirtualMachineNav(page);
21 | this.containerEngine = new ContainerEngineNav(page);
22 | this.kubernetes = new KubernetesNav(page);
23 | this.wsl = new WslNav(page);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/e2e/pages/preferences/kubernetes.ts:
--------------------------------------------------------------------------------
1 | import type { Page, Locator } from '@playwright/test';
2 |
3 | export class KubernetesNav {
4 | readonly page: Page;
5 | readonly nav: Locator;
6 | readonly kubernetesToggle: Locator;
7 | readonly kubernetesVersion: Locator;
8 | readonly kubernetesPort: Locator;
9 | readonly kubernetesOptions: Locator;
10 | readonly kubernetesVersionLockedFields: Locator;
11 |
12 | constructor(page: Page) {
13 | this.page = page;
14 | this.nav = page.locator('[data-test="nav-kubernetes"]');
15 | this.kubernetesToggle = page.locator('[data-test="kubernetesToggle"]');
16 | this.kubernetesVersion = page.locator('[data-test="kubernetesVersion"]');
17 | this.kubernetesPort = page.locator('[data-test="kubernetesPort"]');
18 | this.kubernetesOptions = page.locator('[data-test="kubernetesOptions"]');
19 | this.kubernetesVersionLockedFields = page.locator('[data-test="kubernetesVersion"] > .select-k8s-version > .icon-lock');
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/e2e/pages/preferences/wsl.ts:
--------------------------------------------------------------------------------
1 | import type { Page, Locator } from '@playwright/test';
2 |
3 | export class WslNav {
4 | readonly page: Page;
5 | readonly nav: Locator;
6 | readonly wslIntegrations: Locator;
7 | readonly addressTitle: Locator;
8 | readonly tabIntegrations: Locator;
9 | readonly tabProxy: Locator;
10 |
11 | constructor(page: Page) {
12 | this.page = page;
13 | this.nav = page.locator('[data-test="nav-wsl"]');
14 | this.tabIntegrations = page.locator('.tab >> text=Integrations');
15 | this.tabProxy = page.locator('.tab >> text=Proxy');
16 | this.wslIntegrations = page.locator('[data-test="wslIntegrations"]');
17 | this.addressTitle = page.locator('[data-test="addressTitle"]');
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/e2e/pages/snapshots-page.ts:
--------------------------------------------------------------------------------
1 | import { Locator, Page } from '@playwright/test';
2 |
3 | export class SnapshotsPage {
4 | readonly page: Page;
5 | readonly snapshotsPage: Locator;
6 | readonly createSnapshotButton: Locator;
7 | readonly createSnapshotNameInput: Locator;
8 | readonly createSnapshotDescInput: Locator;
9 |
10 | constructor(page: Page) {
11 | this.page = page;
12 | this.snapshotsPage = page.locator('[data-test="snapshotsPage"]');
13 | this.createSnapshotButton = page.locator('[data-test="createSnapshotButton"]');
14 | this.createSnapshotNameInput = page.locator('[data-test="createSnapshotNameInput"]');
15 | this.createSnapshotDescInput = page.locator('[data-test="createSnapshotDescInput"]');
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/e2e/pages/troubleshooting-page.ts:
--------------------------------------------------------------------------------
1 | import type { Page, Locator } from '@playwright/test';
2 |
3 | export class TroubleshootingPage {
4 | readonly page: Page;
5 | readonly factoryResetButton: Locator;
6 | readonly logsButton: Locator;
7 | readonly troubleshooting: Locator;
8 |
9 | constructor(page: Page) {
10 | this.page = page;
11 | this.factoryResetButton = page.locator('[data-test="factoryResetButton"]');
12 | this.logsButton = page.locator('[data-test="logsButton"]');
13 | this.troubleshooting = page.locator('.troubleshooting');
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/go.work:
--------------------------------------------------------------------------------
1 | go 1.24.0
2 |
3 | toolchain go1.24.2
4 |
5 | use (
6 | ./scripts
7 | ./src/go/docker-credential-none
8 | ./src/go/extension-proxy
9 | ./src/go/guestagent
10 | ./src/go/mock-wsl
11 | ./src/go/nerdctl-stub
12 | ./src/go/nerdctl-stub/generate
13 | ./src/go/networking
14 | ./src/go/rdctl
15 | ./src/go/spin-stub
16 | ./src/go/wsl-helper
17 | )
18 |
--------------------------------------------------------------------------------
/packaging/linux/rancher-desktop.appdata.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | rancher-desktop
4 | CC0-1.0
5 | Apache-2.0
6 | Rancher Desktop
7 | Kubernetes and container management on the desktop
8 |
9 |
10 | Rancher Desktop is an open-source project to bring Kubernetes and container management to the desktop
11 |
12 |
13 |
14 | rancher-desktop
15 |
16 |
17 |
18 |
19 | https://rancherdesktop.io/
20 | https://github.com/rancher-sandbox/rancher-desktop/issues
21 |
22 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/dependencies.yaml:
--------------------------------------------------------------------------------
1 | lima: 1.1.1.rd1
2 | qemu: 9.2.0.rd2
3 | socketVMNet: 1.2.1
4 | alpineLimaISO:
5 | isoVersion: 0.2.43.rd5
6 | alpineVersion: 3.21.3
7 | WSLDistro: "0.84"
8 | kuberlr: 0.6.0
9 | helm: 3.18.1
10 | dockerCLI: 28.2.2
11 | dockerBuildx: 0.24.0
12 | dockerCompose: 2.36.2
13 | golangci-lint: 2.1.6
14 | trivy: 0.63.0
15 | steve: 0.1.0-beta9
16 | rancherDashboard: 2.11.0.rd2
17 | dockerProvidedCredentialHelpers: 0.9.3
18 | ECRCredentialHelper: 0.9.1
19 | mobyOpenAPISpec: "1.50"
20 | wix: v3.14.1
21 | hostSwitch: 1.2.7
22 | moproxy: 0.5.1
23 | spinShim: 0.19.0
24 | spinOperator: 0.5.0
25 | certManager: 1.17.2
26 | spinCLI: 3.2.0
27 | spinKubePlugin: 0.4.0
28 | check-spelling: 0.0.25
29 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/fonts/lato/lato-v17-latin-700.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/pkg/rancher-desktop/assets/fonts/lato/lato-v17-latin-700.woff
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/fonts/lato/lato-v17-latin-700.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/pkg/rancher-desktop/assets/fonts/lato/lato-v17-latin-700.woff2
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/fonts/lato/lato-v17-latin-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/pkg/rancher-desktop/assets/fonts/lato/lato-v17-latin-regular.woff
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/fonts/lato/lato-v17-latin-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/pkg/rancher-desktop/assets/fonts/lato/lato-v17-latin-regular.woff2
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/fonts/poppins/poppins-v15-latin-300.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/pkg/rancher-desktop/assets/fonts/poppins/poppins-v15-latin-300.woff
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/fonts/poppins/poppins-v15-latin-300.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/pkg/rancher-desktop/assets/fonts/poppins/poppins-v15-latin-300.woff2
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/fonts/poppins/poppins-v15-latin-500.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/pkg/rancher-desktop/assets/fonts/poppins/poppins-v15-latin-500.woff
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/fonts/poppins/poppins-v15-latin-500.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/pkg/rancher-desktop/assets/fonts/poppins/poppins-v15-latin-500.woff2
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/fonts/roboto-mono/roboto-mono-v13-latin-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/pkg/rancher-desktop/assets/fonts/roboto-mono/roboto-mono-v13-latin-regular.woff
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/fonts/roboto-mono/roboto-mono-v13-latin-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/pkg/rancher-desktop/assets/fonts/roboto-mono/roboto-mono-v13-latin-regular.woff2
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/scripts/10-flannel.conflist:
--------------------------------------------------------------------------------
1 | {
2 | "name":"cbr0",
3 | "cniVersion":"0.3.1",
4 | "plugins":[
5 | {
6 | "type":"flannel",
7 | "delegate":{
8 | "hairpinMode":true,
9 | "forceAddress":true,
10 | "isDefaultGateway":true
11 | }
12 | },
13 | {
14 | "type":"portmap",
15 | "capabilities":{
16 | "portMappings":true
17 | }
18 | }
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/scripts/buildkit.confd:
--------------------------------------------------------------------------------
1 | # config file for /etc/init.d/buildkit
2 |
3 | # overrides the main command executed by the supervise daemon
4 | buildkitd_command="/usr/local/bin/buildkitd"
5 |
6 | # any other options you want to pass to buildkitd_command
7 | buildkitd_opts="--addr=unix:///run/buildkit/buildkitd.sock --containerd-worker=true --containerd-worker-addr=/run/k3s/containerd/containerd.sock --containerd-worker-gc --oci-worker=false"
8 |
9 | # Settings for process limits (ulimit)
10 | #ulimit_opts="-c unlimited -n 1048576 -u unlimited"
11 |
12 | # seconds to wait for sending SIGTERM and SIGKILL signals when stopping buildkitd
13 | #signal_retry="TERM/60/KILL/10"
14 |
15 | # where buildkit stdout (and perhaps stderr) goes.
16 | #log_file="/var/log/buildkit.log"
17 |
18 | # where buildkit stderr optionally goes.
19 | # if this is not set, the value in 'logfile' is used
20 | #err_file="/var/log/buildkit-err.log"
21 |
22 | # mode of the log files
23 | #log_mode=0644
24 |
25 | # user that owns the log files (no group root on WSL)
26 | log_owner=root
27 |
28 | # to override the default supervise_daemon_args
29 | #supervise_daemon_opts=""
30 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/scripts/buildkit.initd:
--------------------------------------------------------------------------------
1 | #!/sbin/openrc-run
2 | supervisor=supervise-daemon
3 |
4 | name="BuildKit Daemon"
5 | description="Standalone buildkitd"
6 |
7 | command="${buildkitd_command:-/usr/bin/buildkitd}"
8 | command_args="${buildkitd_opts:---oci-worker=false --containerd-worker=true}"
9 | rc_ulimit="${ulimit_opts:--c unlimited -n 1048576 -u unlimited}"
10 | retry="${signal_retry:-TERM/60/KILL/10}"
11 |
12 | log_file="${log_file:-/var/log/${RC_SVCNAME}.log}"
13 | err_file="${err_file:-${log_file}}"
14 | log_mode="${log_mode:-0644}"
15 | log_owner="${log_owner:-root}"
16 |
17 | supervise_daemon_args="${supervise_daemon_opts:---stderr \"${err_file}\" --stdout \"${log_file}\"}"
18 |
19 | start_pre() {
20 | checkpath -f -m "$log_mode" -o "$log_owner" "$log_file" "$err_file"
21 | }
22 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/scripts/cert-manager.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: v1
3 | kind: Namespace
4 | metadata:
5 | name: cert-manager
6 | ---
7 | apiVersion: helm.cattle.io/v1
8 | kind: HelmChart
9 | metadata:
10 | name: cert-manager
11 | namespace: kube-system
12 | spec:
13 | chart: "https://%{KUBERNETES_API}%/static/rancher-desktop/cert-manager.tgz"
14 | targetNamespace: cert-manager
15 | # Old versions of the helm-controller don't support createNamespace, so we
16 | # created the namespace ourselves.
17 | createNamespace: false
18 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/scripts/docker-credential-rancher-desktop:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -eu
4 |
5 | source /etc/rancher/desktop/credfwd
6 |
7 | DATA="@-"
8 | # The "list" command doesn't have a payload on STDIN
9 | [ "$1" = "list" ] && DATA=""
10 |
11 | # $CREDFWD_CURL_OPTS is intentionally *not* quoted
12 | exec curl --silent --user "$CREDFWD_AUTH" --data "$DATA" --noproxy '*' --fail-with-body ${CREDFWD_CURL_OPTS:-} "$CREDFWD_URL/$1"
13 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/scripts/install-containerd-shims:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -o errexit -o nounset -o pipefail
4 |
5 | dest=/usr/local/containerd-shims
6 |
7 | # Copy all shims into the data volume so they become part of snapshots.
8 | # TODO Maybe use rsync to avoid copying files repeatedly?
9 | mkdir -p "$dest"
10 | for dir in "$@"; do
11 | if [[ "$(uname -a)" =~ microsoft ]]; then
12 | dir=$(wslpath -a -u "$dir")
13 | fi
14 | cp "${dir}/containerd-shim-"* "$dest" || :
15 | done
16 |
17 | # Make sure all shims are executable.
18 | for file in "${dest}/"*; do
19 | if [ -e "$file" ]; then
20 | chmod 755 "$file"
21 | fi
22 | done
23 |
24 | # Create symlinks to each shim into /usr/local/bin.
25 | # In the future this will enable us putting only shims from an allow list on the PATH.
26 | find /usr/local/bin -type l -name 'containerd-shim-*' -delete
27 | find "$dest" -type f -exec ln -sf {} /usr/local/bin \;
28 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/scripts/install-wsl-helpers:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # This script installs WSL helpers into the shared WSL mount at `/mnt/wsl`.
4 | # Usage: $0
5 |
6 | # shellcheck shell=ash
7 |
8 | set -o errexit -o nounset
9 |
10 | # The nerdctl shim must be setuid root to be able to create bind mounts within
11 | # /mnt/wsl so that nerdctl can see it.
12 | mkdir -p "/mnt/wsl/rancher-desktop/bin/"
13 | cp "${1}" "/mnt/wsl/rancher-desktop/bin/nerdctl"
14 | chmod u+s "/mnt/wsl/rancher-desktop/bin/nerdctl"
15 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/scripts/k3s-containerd-config.toml:
--------------------------------------------------------------------------------
1 | version = 2
2 |
3 | root = "/var/lib/rancher/k3s/agent/containerd"
4 | state = "/run/k3s/containerd"
5 |
6 | [grpc]
7 | address = "/run/k3s/containerd/containerd.sock"
8 |
9 | [plugins."io.containerd.internal.v1.opt"]
10 | path = "/var/lib/rancher/k3s/agent/containerd"
11 |
12 | [plugins."io.containerd.grpc.v1.cri"]
13 | stream_server_address = "127.0.0.1"
14 | stream_server_port = "10010"
15 | enable_selinux = false
16 | enable_unprivileged_ports = true
17 | enable_unprivileged_icmp = true
18 | sandbox_image = "rancher/mirrored-pause:3.6"
19 |
20 | [plugins."io.containerd.grpc.v1.cri".containerd]
21 | snapshotter = "overlayfs"
22 | disable_snapshot_annotations = true
23 |
24 | [plugins."io.containerd.grpc.v1.cri".cni]
25 | bin_dir = "/usr/libexec/cni"
26 | conf_dir = "/etc/cni/net.d"
27 |
28 | [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
29 | runtime_type = "io.containerd.runc.v2"
30 |
31 | [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
32 | SystemdCgroup = false
33 |
34 | [plugins."io.containerd.grpc.v1.cri".registry]
35 | config_path = "/var/lib/rancher/k3s/agent/etc/containerd/certs.d"
36 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/scripts/logrotate-k3s:
--------------------------------------------------------------------------------
1 | /var/log/k3s.log {
2 | missingok
3 | notifempty
4 | copytruncate
5 | }
6 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/scripts/logrotate-lima-guestagent:
--------------------------------------------------------------------------------
1 | /var/log/lima-guestagent.log {
2 | missingok
3 | notifempty
4 | copytruncate
5 | }
6 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/scripts/logrotate-openresty:
--------------------------------------------------------------------------------
1 | /var/log/openresty/*.log {
2 | missingok
3 | sharedscripts
4 | postrotate
5 | /etc/init.d/rd-openresty --quiet --ifstarted reopen
6 | endscript
7 | }
8 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/scripts/nerdctl:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | export CONTAINERD_ADDRESS=/run/k3s/containerd/containerd.sock
3 | if [ -f /usr/local/openresty/nginx/conf/allowed-images.conf ]; then
4 | export HTTPS_PROXY=http://127.0.0.1:3128
5 | fi
6 |
7 | # On WSL, we need to enter the correct pid &c. namespace for nerdctl to work
8 | # correctly.
9 |
10 | if [ -r /run/wsl-init.pid ]; then
11 | parent="$(cat /run/wsl-init.pid)"
12 | pid="$(ps -o pid,ppid,comm | awk '$2 == "'"${parent}"'" && $3 == "init" { print $1 }')"
13 | if [ -n "${pid}" ]; then
14 | exec /usr/bin/nsenter -p -m -n -t "${pid}" /usr/local/libexec/nerdctl/nerdctl "$@"
15 | fi
16 | fi
17 |
18 | exec /usr/local/libexec/nerdctl/nerdctl "$@"
19 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/scripts/service-cri-dockerd.initd:
--------------------------------------------------------------------------------
1 | #!/sbin/openrc-run
2 |
3 | # This script is used to manage cri-dockerd via OpenRC.
4 |
5 | # shellcheck shell=ksh
6 |
7 | name="cri-dockerd"
8 | description="Rancher Desktop Shim for Docker Engine"
9 |
10 |
11 | supervisor=supervise-daemon
12 | command=/usr/local/bin/cri-dockerd
13 | command_args="--container-runtime-endpoint unix:///run/cri-dockerd.sock --network-plugin=cni --cni-bin-dir=/usr/libexec/cni --cni-conf-dir=/etc/cni/net.d --cni-cache-dir=/var/lib/cni/cache"
14 |
15 | CRI_DOCKERD_LOGFILE="${CRI_DOCKERD_LOGFILE:-${LOG_DIR:-/var/log}/${RC_SVCNAME}.log}"
16 | output_log="'${CRI_DOCKERD_LOGFILE}'"
17 | error_log="'${CRI_DOCKERD_LOGFILE}'"
18 |
19 | depend() {
20 | need docker
21 | }
22 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/scripts/service-wsl-dockerd.initd:
--------------------------------------------------------------------------------
1 | #!/sbin/openrc-run
2 |
3 | # This is an OpenRC service script (/etc/init.d/wsl-dockerd) that runs
4 | # wsl-helper docker-proxy start.
5 |
6 | # shellcheck shell=ksh
7 |
8 | name="Rancher Desktop Docker Daemon"
9 | description="Starts dockerd for Rancher Desktop"
10 |
11 | supervisor=supervise-daemon
12 | if [ -f /usr/local/openresty/nginx/conf/allowed-images.conf ]; then
13 | supervise_daemon_args="-e HTTPS_PROXY=http://127.0.0.1:3128"
14 | fi
15 | command="'${WSL_HELPER_BINARY:-/usr/local/bin/wsl-helper}'"
16 | command_args="docker-proxy start"
17 |
18 | DOCKER_LOGFILE="${DOCKER_LOGFILE:-${LOG_DIR:-/var/log}/${RC_SVCNAME}.log}"
19 | output_log="'${DOCKER_LOGFILE}'"
20 | error_log="'${DOCKER_LOGFILE}'"
21 |
22 | rc_ulimit="${DOCKER_ULIMIT:--c unlimited -n 1048576 -u unlimited}"
23 |
24 | depend() {
25 | need sysfs cgroups
26 | after iptables ip6tables
27 | }
28 |
29 | healthcheck() {
30 | /usr/bin/curl --fail --unix-socket /mnt/wsl/rancher-desktop/run/docker.sock --url http://./_ping
31 | }
32 | healthcheck_timer=60
33 | respawn_delay=5
34 | respawn_max=10
35 | respawn_period=10
36 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/scripts/spin-operator.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: core.spinkube.dev/v1alpha1
3 | kind: SpinAppExecutor
4 | metadata:
5 | name: containerd-shim-spin
6 | spec:
7 | createDeployment: true
8 | deploymentConfig:
9 | runtimeClassName: spin
10 | ---
11 | apiVersion: v1
12 | kind: Namespace
13 | metadata:
14 | name: spin-operator
15 | ---
16 | apiVersion: helm.cattle.io/v1
17 | kind: HelmChart
18 | metadata:
19 | name: spin-operator
20 | namespace: kube-system
21 | spec:
22 | chart: "https://%{KUBERNETES_API}%/static/rancher-desktop/spin-operator.tgz"
23 | targetNamespace: spin-operator
24 | # Old versions of the helm-controller don't support createNamespace, so we
25 | # created the namespace ourselves.
26 | createNamespace: false
27 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/scripts/wsl-data.conf:
--------------------------------------------------------------------------------
1 | # This is the /etc/wsl.conf for use with rancher-desktop-data
2 | # As we do not have an actual data distribution, this file is included as part
3 | # of the application and written out at runtime.
4 |
5 | [automount]
6 | # Prevent processing /etc/fstab, since it doesn't exist.
7 | mountFsTab = false
8 | # Prevent running ldconfig, since that doesn't exist.
9 | ldconfig = false
10 | # Needed for compatibility with some `yarn` scenarios.
11 | options = metadata
12 |
13 | # We _do_ want to generate `/etc/hosts` here, so that it can be used by the main
14 | # distribution.
15 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/specs/README.md:
--------------------------------------------------------------------------------
1 | ## Generators
2 |
3 | ### To generate go code:
4 |
5 | `oapi-codegen pkg/rancher-desktop/assets/specs/command-api.yaml > api/commands.go`
6 |
7 | #### Dependencies:
8 |
9 | * opai-codegen: To install:
10 |
11 | ```bash
12 | go get github.com/deepmap/oapi-codegen/cmd/oapi-codegen
13 | ```
14 |
15 | ### To generate documentation:
16 |
17 | ```
18 | mkdir tmp
19 | docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli:v5.4.2 generate -i /local/src/assets/specs/command-api.yaml -g html -o /local/tmp/
20 | open tmp/index.html # (macOS)
21 | start tmp/index.html # (Powershell)
22 | xdg-open tmp/index.html # (linux, replace with path to a specific browser if you prefer).
23 | ```
24 |
25 | Recommended tag: openapitools/openapi-generator-cli:v5.4.2
26 |
27 | So run:
28 | ```
29 | docker run ... openapitools/openapi-generator-cli@sha256:3d7c84e4b8f25a2074d6ab44d936cd69d08a223021197269e75d29992204e15e
30 | ```
31 |
32 | ## References:
33 |
34 | * OpenAPI spec: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#mediaTypeObject
35 |
36 | * Tools: https://openapi.tools/
37 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/styles/app.scss:
--------------------------------------------------------------------------------
1 | @import "./vendor/normalize";
2 |
3 | @import "./base/variables";
4 | @import "./base/functions";
5 | @import "./base/mixins";
6 | @import "./base/helpers";
7 | @import "./base/color";
8 | @import "./base/basic";
9 | @import "./base/typography";
10 |
11 | @import "./fonts/fontstack";
12 | @import "./fonts/dots";
13 | @import "./fonts/zerowidthspace";
14 | @import "./fonts/icons";
15 |
16 | @import "./themes/light";
17 | @media screen and (prefers-color-scheme: dark) {
18 | @import "./themes/dark";
19 | }
20 | @import './themes/_suse.scss';
21 |
22 |
23 | @import "./global/columns";
24 | @import "./global/cards";
25 | @import "./global/button";
26 | @import "./global/form";
27 | @import "./global/gauges";
28 | @import "./global/labeled-input";
29 | @import "./global/tooltip";
30 | @import "./global/table";
31 | @import "./global/select";
32 | @import "./global/resource";
33 |
34 | @import "./vendor/vue-select";
35 | @import "./vendor/vue-js-modal";
36 |
37 | @import "./rancher-desktop.scss";
38 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/styles/base/_color.scss:
--------------------------------------------------------------------------------
1 | .bg-transparent {
2 | background-color: transparent;
3 | }
4 |
5 | .bg-disabled {
6 | background-color: var(--disabled-bg) !important;
7 | }
8 |
9 | .text-disabled {
10 | color: var(--disabled-text) !important;
11 | }
12 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/styles/base/_typography.scss:
--------------------------------------------------------------------------------
1 | HTML, BODY {
2 | font-family: $body-font;
3 | font-size: 14px;
4 | }
5 |
6 | H1, H2, H3, H4, H5, H6 {
7 | color: var(--body-text);
8 | font-style: normal;
9 | font-weight: 400;
10 | margin: 0 0 10px 0;
11 | }
12 |
13 | H1 {
14 | font-size: 24px;
15 | }
16 |
17 | H2 {
18 | font-size: 21px;
19 | }
20 |
21 | H3 {
22 | font-size: 18px;
23 | }
24 |
25 | H4 {
26 | font-size: 16px;
27 | }
28 |
29 | H5 {
30 | font-size: 14px;
31 | }
32 |
33 | H6 {
34 | font-size: 12px;
35 | text-transform: uppercase;
36 | }
37 |
38 | P {
39 | font-weight: 400;
40 | font-style: normal;
41 | margin: 0;
42 | }
43 |
44 | //code
45 | code, samp, kbd, .monospace {
46 | font-family: $mono-font;
47 | text-align: left;
48 | }
49 |
50 | pre {
51 | padding: 10px;
52 | border-radius: var(--border-radius);
53 | background: var(--box-bg);
54 | margin: 5px;
55 | overflow: auto;
56 | }
57 |
58 | code {
59 | background-color: var(--box-bg);
60 | display: inline-block;
61 | padding: 5px;
62 | border: 1px solid var(--border);
63 | border-radius: var(--border-radius);
64 | }
65 |
66 | pre code {
67 | background: transparent;
68 | padding: 0;
69 | }
70 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/styles/base/_variables.scss:
--------------------------------------------------------------------------------
1 | $header-font: 'Poppins', sans-serif;
2 | $body-font: 'Lato', arial, helvetica, sans-serif;
3 | $mono-font: 'Roboto Mono', monospace;
4 |
5 | $max-width: 1440px !default;
6 | $min-width: 75% !default;
7 | $input-height: 61px;
8 |
9 | $input-padding-lg: 18px;
10 | $input-padding-sm: 10px;
11 | $input-line-height: 18px;
12 |
13 | $column-gutter: 1.75%;
14 |
15 | $sideways-tabs-width: 200px;
16 |
17 | $array-list-remove-margin: 75px;
18 |
19 | $z-indexes: (
20 | zero: 0,
21 | default: 1,
22 | overContent: 2,
23 | hoverOverContent: 3,
24 |
25 | tableGroup: 10,
26 | fixedTableHeader: 11,
27 |
28 | modalOverlay: 20,
29 | modalContent: 21,
30 |
31 | tooltip: 30,
32 |
33 | dropdownOverlay: 40,
34 | dropdownContent: 41,
35 |
36 | loadingOverlay: 50,
37 | loadingContent: 51
38 | );
39 |
40 | // Usage Example:
41 | // @media only screen and (min-width: map-get($breakpoints, '--viewport-*')) {
42 | // }
43 | $breakpoints: (
44 | '--viewport-4': 480px,
45 | '--viewport-7': 768px,
46 | '--viewport-9': 992px,
47 | '--viewport-12': 1281px,
48 | );
49 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/styles/rancher-desktop.scss:
--------------------------------------------------------------------------------
1 | /** Rancher Desktop specific styles */
2 | body {
3 | background-color: var(--body-bg);
4 | color: var(--body-text);
5 | font-size: 14px;
6 | }
7 |
8 | .labeled-input {
9 | margin-bottom: 1em;
10 | }
11 | label > button:first-child:not(.btn-sm) {
12 | margin-right: 1em;
13 | }
14 |
15 | .locked-radio .radio-container span.radio-custom {
16 | &[aria-checked="true"] {
17 | opacity: 1;
18 | }
19 |
20 | &:not([aria-checked="true"]) {
21 | opacity: 1;
22 | background-color: var(--radio-locked-bg);
23 | box-shadow: var(--radio-locked-shadow);
24 | }
25 | }
26 |
27 | @media screen and (prefers-color-scheme: dark) {
28 | option {
29 | background-color: var(--input-bg);
30 | }
31 | }
32 |
33 | :is(.btn, button, [class*='btn-']):not([class*='role-']) {
34 | /* buttons should have one of the role- classes:
35 | * .role-primary, .role-secondary, .role-tertiary, .role-multi-action, etc.
36 | */
37 | outline: 10px dashed red !important;
38 | }
39 |
40 | .btn-icon-text {
41 | display: flex;
42 | align-items: center;
43 | gap: 0.5rem;
44 | }
45 |
46 | :root {
47 | --preferences-content-padding: 0.75rem;
48 | }
49 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/assets/styles/vendor/vue-js-modal.scss:
--------------------------------------------------------------------------------
1 | /* NOTE: Commenting out everything in this Sass file for the time being. Rancher
2 | * Desktop does not use vue-js-modal in any capacity and modals are handled via
3 | * native windows.
4 | *
5 | * @import '~/../../node_modules/vue-js-modal/dist/styles.css';
6 | *
7 | * .v--modal-overlay {
8 | * background-color: var(--overlay-bg);
9 | * z-index: z-index('modalOverlay');
10 | * }
11 | *
12 | * .v--modal {
13 | * background-color: var(--modal-bg)!important;
14 | * box-shadow: none;
15 | * border: 2px solid var(--modal-border);
16 | * }
17 | */
18 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/backend/containerClient/index.ts:
--------------------------------------------------------------------------------
1 | export * from './types';
2 | export { MobyClient } from './mobyClient';
3 | export { NerdctlClient } from './nerdctlClient';
4 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/Alert.vue:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
30 |
34 |
38 | {{ bannerText }}
39 |
40 |
41 |
42 |
43 |
56 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/DashboardOpen.vue:
--------------------------------------------------------------------------------
1 |
26 |
27 |
28 |
36 |
37 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/ExtensionsError.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
Error rendering extension: {{ extensionId }}
22 |
23 | {{ error }}
24 |
25 |
26 |
27 |
28 |
33 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/ImageAddTabs.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
14 |
19 |
20 |
21 |
22 |
23 |
50 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/ImagesButtonAdd.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
25 |
26 |
35 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/NavItem.vue:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
12 |
16 |
17 |
18 |
19 |
20 | Extensions
21 |
22 |
23 |
24 |
25 |
26 |
55 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/Preferences/ButtonOpen.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
20 |
21 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/Preferences/Help.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/Preferences/ModalHeader.vue:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
12 |
13 |
14 |
30 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/Preferences/ModalNavItem.vue:
--------------------------------------------------------------------------------
1 |
28 |
29 |
30 |
35 | Menu Item
36 |
37 |
38 |
39 |
52 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/Preferences/VirtualMachineVolumes.vue:
--------------------------------------------------------------------------------
1 |
27 |
28 |
29 |
30 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/SnapshotsButtonCreate.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
25 |
26 |
35 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/SortableTable/grouping.js:
--------------------------------------------------------------------------------
1 | import { get } from '@pkg/utils/object';
2 |
3 | export default {
4 | computed: {
5 | groupedRows() {
6 | const groupKey = this.groupBy;
7 | const refKey = this.groupRef || groupKey;
8 |
9 | if ( !groupKey) {
10 | return [{
11 | key: 'default',
12 | ref: 'default',
13 | rows: this.pagedRows,
14 | }];
15 | }
16 |
17 | const out = [];
18 | const map = {};
19 |
20 | for ( const obj of this.pagedRows ) {
21 | const key = get(obj, groupKey) || '';
22 | const ref = get(obj, refKey);
23 | let entry = map[key];
24 |
25 | if ( entry ) {
26 | entry.rows.push(obj);
27 | } else {
28 | entry = {
29 | key,
30 | ref,
31 | rows: [obj],
32 | };
33 | map[key] = entry;
34 | out.push(entry);
35 | }
36 | }
37 |
38 | return out;
39 | },
40 | },
41 | };
42 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/TroubleshootingLineItem.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
42 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/__tests__/PreferencesButton.spec.ts:
--------------------------------------------------------------------------------
1 | import { shallowMount } from '@vue/test-utils';
2 |
3 | import PreferencesButton from '../Preferences/ButtonOpen.vue';
4 |
5 | describe('Preferences/ButtonOpen.vue', () => {
6 | it(`renders a button`, () => {
7 | const wrapper = shallowMount(PreferencesButton, { mocks: { t: jest.fn() } });
8 |
9 | expect(wrapper.find('button').classes()).toStrictEqual(['btn', 'role-secondary', 'btn-icon-text']);
10 | });
11 |
12 | it(`emits 'open-preferences' on click`, () => {
13 | const wrapper = shallowMount(PreferencesButton, { mocks: { t: jest.fn() } });
14 |
15 | wrapper.find('button').trigger('click');
16 |
17 | expect(wrapper.emitted('open-preferences')).toHaveLength(1);
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/form/LabeledBadge.vue:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
31 |
32 |
33 |
40 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/components/form/TooltipIcon.vue:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
28 |
29 |
30 |
41 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/config/cookies.js:
--------------------------------------------------------------------------------
1 | export const CSRF = 'CSRF';
2 | export const USERNAME = 'R_USERNAME';
3 | export const LOCALE = 'R_LOCALE';
4 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/config/emptyStubForJSLinter.js:
--------------------------------------------------------------------------------
1 | // See https://stackoverflow.com/questions/39418555/syntaxerror-with-jest-and-react-and-importing-css-files
2 | // to continue to use jest-based unit-testing with CSS import statements.
3 |
4 | module.exports = {};
5 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/config/private-label.js:
--------------------------------------------------------------------------------
1 | import { SETTING } from './settings';
2 |
3 | export const ANY = 0;
4 | export const STANDARD = 1;
5 | export const CUSTOM = 2;
6 |
7 | const STANDARD_VENDOR = 'Rancher';
8 | const STANDARD_PRODUCT = 'Explorer';
9 |
10 | let mode = STANDARD;
11 | let vendor = STANDARD_VENDOR;
12 | let product = STANDARD_PRODUCT;
13 |
14 | export function setMode(m) {
15 | mode = m;
16 | }
17 |
18 | export function setVendor(v) {
19 | vendor = v;
20 | }
21 |
22 | export function setProduct(p) {
23 | product = p;
24 | }
25 |
26 | // -------------------------------------
27 |
28 | export function getMode() {
29 | return mode;
30 | }
31 |
32 | export function isStandard() {
33 | return mode === STANDARD;
34 | }
35 |
36 | export function matches(pl) {
37 | if ( pl === ANY ) {
38 | return true;
39 | }
40 |
41 | return pl === mode;
42 | }
43 |
44 | export function getVendor() {
45 | if ( vendor === SETTING.PL_RANCHER_VALUE ) {
46 | return STANDARD_VENDOR;
47 | }
48 |
49 | return vendor;
50 | }
51 |
52 | export function getProduct() {
53 | return product;
54 | }
55 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/hocs/README.md:
--------------------------------------------------------------------------------
1 | Higher-Order Components (HOCs) are functions that take in a component as an argument and return a new component with additional functionality. HOCs are a useful pattern for reusing component logic and implementing cross-cutting concerns, such as authentication and authorization, caching, logging, and error handling. They allow for extracting common functionality into a separate component and apply it to multiple components without duplicating code.
2 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/index.ts:
--------------------------------------------------------------------------------
1 | /***
2 | * NOTE: @rancher/shell was removed from this project during the Nuxt removal.
3 | * I'm keeping this file around for it's eventual reintroduction; it was easier
4 | * to limit the potential scope of issues associated with the Nuxt removal by
5 | * removing @rancher/shell
6 | */
7 | // import { importTypes } from '@rancher/auto-import';
8 | // import { IPlugin } from '@shell/core/types';
9 |
10 | // import routes from './router';
11 |
12 | // // Init the package
13 | // export default function(plugin: IPlugin) {
14 | // // Auto-import model, detail, edit from the folders
15 | // importTypes(plugin);
16 |
17 | // // Provide plugin metadata from package.json
18 | // plugin.metadata = require('./package.json');
19 |
20 | // // Load a product
21 | // plugin.addProduct(require('./product'));
22 |
23 | // plugin.addRoutes(routes);
24 | // }
25 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/integrations/pathManager.ts:
--------------------------------------------------------------------------------
1 | // Definitions only
2 |
3 | /**
4 | * PathManager is the interface that anything that manages the
5 | * PATH variable must implement.
6 | */
7 | export interface PathManager {
8 | /** The PathManagementStrategy that corresponds to the implementation. */
9 | readonly strategy: PathManagementStrategy
10 | /**
11 | * Applies changes to the system. Should be idempotent, and should not throw
12 | * any exceptions.
13 | */
14 | enforce(): Promise
15 | /**
16 | * Removes any changes that the PathManager may have made. Should be
17 | * idempotent, and should not throw any exceptions.
18 | */
19 | remove(): Promise
20 | }
21 |
22 | /**
23 | * ManualPathManager is for when the user has chosen to manage
24 | * their PATH themselves. It does nothing.
25 | */
26 | export class ManualPathManager implements PathManager {
27 | readonly strategy = PathManagementStrategy.Manual;
28 | async enforce(): Promise {}
29 | async remove(): Promise {}
30 | }
31 |
32 | export enum PathManagementStrategy {
33 | Manual = 'manual',
34 | RcFiles = 'rcfiles',
35 | }
36 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/layouts/preferences.vue:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
35 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/main/credentialServer/README.md:
--------------------------------------------------------------------------------
1 | # Credential Helper Server protocol
2 |
3 | This server isn't intended to be used publicly;
4 | it's for other tools that we use in order to find docker credentials.
5 |
6 | The protocol is described at [https://github.com/docker/docker-credential-helpers#development](https://github.com/docker/docker-credential-helpers#development).
7 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/main/diagnostics/__tests__/rdBinInShell.spec.ts:
--------------------------------------------------------------------------------
1 | import { RDBinInShellPath } from '../rdBinInShell';
2 |
3 | describe(RDBinInShellPath, () => {
4 | it('should remove trailing slashes', () => {
5 | expect(RDBinInShellPath.removeTrailingSlash('/Users/mikey/.rd/bin/')).toBe('/Users/mikey/.rd/bin');
6 | expect(RDBinInShellPath.removeTrailingSlash('/Users/mikey/.rd/bin////')).toBe('/Users/mikey/.rd/bin');
7 | expect(RDBinInShellPath.removeTrailingSlash('/Users/mikey/.rd/bin')).toBe('/Users/mikey/.rd/bin');
8 | expect(RDBinInShellPath.removeTrailingSlash('/')).toBe('/');
9 | expect(RDBinInShellPath.removeTrailingSlash('//')).toBe('/');
10 | expect(RDBinInShellPath.removeTrailingSlash('/////')).toBe('/');
11 | expect(RDBinInShellPath.removeTrailingSlash('')).toBe('');
12 | });
13 | });
14 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/main/diagnostics/mockForScreenshots.ts:
--------------------------------------------------------------------------------
1 | import { DiagnosticsCategory, DiagnosticsChecker } from './types';
2 |
3 | /**
4 | * Sample tests for testing
5 | */
6 | class MockChecker implements DiagnosticsChecker {
7 | get id() {
8 | return 'MOCK_CHECKER';
9 | }
10 |
11 | category = DiagnosticsCategory.Utilities;
12 | applicable(): Promise {
13 | return Promise.resolve(!!process.env.RD_MOCK_FOR_SCREENSHOTS);
14 | }
15 |
16 | check() {
17 | return Promise.resolve({
18 | passed: false,
19 | documentation: 'https://www.example.com/not-a-valid-link',
20 | description: `The \`~/.rd/bin\` directory has not been added to the \`PATH\`, so command-line utilities are not configured in your shell.`,
21 | fixes: [],
22 | });
23 | }
24 | }
25 |
26 | export default [new MockChecker()];
27 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/main/diagnostics/testCheckers.ts:
--------------------------------------------------------------------------------
1 | import { DiagnosticsCategory, DiagnosticsChecker } from './types';
2 |
3 | import { isDevEnv } from '@pkg/utils/environment';
4 |
5 | /**
6 | * Sample tests for testing
7 | */
8 | class CheckTesting implements DiagnosticsChecker {
9 | pass: boolean;
10 | constructor(pass: boolean) {
11 | this.pass = pass;
12 | }
13 |
14 | get id() {
15 | return `STATIC_${ this.pass.toString().toUpperCase() }`;
16 | }
17 |
18 | category = DiagnosticsCategory.Testing;
19 | applicable(): Promise {
20 | return Promise.resolve(isDevEnv && !process.env.RD_MOCK_FOR_SCREENSHOTS);
21 | }
22 |
23 | check() {
24 | return Promise.resolve({
25 | passed: this.pass,
26 | documentation: 'https://www.example.com/not-a-valid-link',
27 | description: `This is a \`sample\` test that will **${ this.pass ? 'always' : 'never' }** pass.`,
28 | fixes: [],
29 | });
30 | }
31 | }
32 |
33 | export default [new CheckTesting(true), new CheckTesting(false)];
34 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/main/extensions/index.ts:
--------------------------------------------------------------------------------
1 | export * from './types';
2 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/main/snapshots/types.ts:
--------------------------------------------------------------------------------
1 | export type SnapshotEvent = {
2 | type?: 'restore' | 'delete' | 'create' | 'confirm' | 'backend-lock',
3 | result?: 'success' | 'cancel' | 'error',
4 | error?: string,
5 | snapshotName?: string,
6 | eventTime?: string,
7 | };
8 |
9 | export type SpawnResult = {
10 | stdout: string,
11 | stderr: string,
12 | error?: any,
13 | };
14 |
15 | export interface SnapshotDialog {
16 | header: string,
17 | snapshot?: Snapshot,
18 | message?: string,
19 | detail?: string,
20 | info?: string | null,
21 | showProgressBar?: boolean,
22 | type?: string,
23 | snapshotEventType?: SnapshotEvent['type'],
24 | }
25 |
26 | export interface Snapshot {
27 | name: string,
28 | created: string,
29 | description?: string,
30 | }
31 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/middleware/i18n.js:
--------------------------------------------------------------------------------
1 | export default async function({
2 | isHMR, app, store, route, params, error, redirect,
3 | }) {
4 | // If middleware is called from hot module replacement, ignore it
5 | if (isHMR) {
6 | return;
7 | }
8 |
9 | await store.dispatch('i18n/init');
10 | }
11 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/middleware/indexRedirect.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This middleware redirects / to /General
3 | */
4 | export default ({ route, next, redirect }) => {
5 | switch (route.path) {
6 | case process.env.RD_ENV_PLUGINS_DEV:
7 | next();
8 | break;
9 | case '/':
10 | redirect(301, '/General');
11 | break;
12 | default:
13 | next();
14 | }
15 | };
16 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/nuxt/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016-present - Nuxt Team
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/nuxt/components/nuxt-link.server.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | export default {
4 | name: 'NuxtLink',
5 | extends: Vue.component('RouterLink'),
6 | props: {
7 | prefetch: {
8 | type: Boolean,
9 | default: false
10 | },
11 | noPrefetch: {
12 | type: Boolean,
13 | default: false
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/nuxt/cookie-universal-nuxt.js:
--------------------------------------------------------------------------------
1 | import cookieUniversal from 'cookie-universal'
2 |
3 | export default ({ req, res }, inject) => {
4 | const options = {
5 | "alias": "cookies",
6 | "parseJSON": true
7 | }
8 | inject(options.alias, cookieUniversal(req, res, options.parseJSON))
9 | }
10 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/nuxt/empty.js:
--------------------------------------------------------------------------------
1 | // This file is intentionally left empty for noop aliases
2 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/nuxt/middleware.js:
--------------------------------------------------------------------------------
1 | const middleware = {}
2 |
3 | middleware['i18n'] = require('../middleware/i18n.js')
4 | middleware['i18n'] = middleware['i18n'].default || middleware['i18n']
5 |
6 | middleware['indexRedirect'] = require('../middleware/indexRedirect.js')
7 | middleware['indexRedirect'] = middleware['indexRedirect'].default || middleware['indexRedirect']
8 |
9 | export default middleware
10 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/nuxt/views/app.template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ HEAD }}
5 |
6 |
7 | {{ APP }}
8 |
9 |
10 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/pages/DenyRoot.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Cannot run as Root
5 |
6 |
7 | Rancher Desktop cannot be run with root privileges.
8 | Please run again as a regular user.
9 |
10 |
11 |
18 |
19 |
20 |
21 |
22 |
39 |
40 |
45 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/pages/Diagnostics.vue:
--------------------------------------------------------------------------------
1 |
27 |
28 |
29 |
33 |
34 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/pages/Snapshots.vue:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
24 |
25 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/plugins/clean-html-directive.js:
--------------------------------------------------------------------------------
1 | import DOMPurify from 'dompurify';
2 | import Vue from 'vue';
3 |
4 | const ALLOWED_TAGS = [
5 | 'code',
6 | 'li',
7 | 'a',
8 | 'p',
9 | 'b',
10 | 'br',
11 | 'ul',
12 | 'pre',
13 | 'span',
14 | 'div',
15 | 'i',
16 | 'em',
17 | 'strong',
18 | ];
19 |
20 | const purifyHTML = value => DOMPurify.sanitize(value, { ALLOWED_TAGS });
21 |
22 | export const cleanHtmlDirective = {
23 | inserted(el, binding) {
24 | el.innerHTML = purifyHTML(binding.value);
25 | },
26 | componentUpdated(el, binding) {
27 | el.innerHTML = purifyHTML(binding.value);
28 | },
29 | unbind(el) {
30 | el.innerHTML = '';
31 | },
32 | };
33 |
34 | Vue.directive('clean-html', cleanHtmlDirective);
35 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/plugins/directives.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 |
3 | Vue.directive('focus', {
4 | inserted(_el, _binding, vnode) {
5 | const element = getElement(vnode);
6 |
7 | if (element) {
8 | element.focus();
9 | }
10 | },
11 | });
12 |
13 | const getElement = (vnode) => {
14 | const { componentInstance, componentOptions: { tag } } = vnode;
15 |
16 | if (tag === 'labeled-input') {
17 | return componentInstance.$refs.value;
18 | }
19 | };
20 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/plugins/shortkey.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import ShortKey from 'vue-shortkey';
3 |
4 | Vue.use(ShortKey, { prevent: ['input', 'textarea', 'select'] });
5 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/plugins/tooltip.js:
--------------------------------------------------------------------------------
1 | import vTooltip from 'v-tooltip';
2 | import Vue from 'vue';
3 |
4 | Vue.use(vTooltip);
5 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/plugins/trim-whitespace.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 |
3 | export function trimWhitespace(el, dir) {
4 | for (const node of el.childNodes) {
5 | if (node.nodeType === Node.TEXT_NODE ) {
6 | const trimmed = node.data.trim();
7 |
8 | if ( trimmed === '') {
9 | node.remove();
10 | } else if ( trimmed !== node.data ) {
11 | node.data = trimmed;
12 | }
13 | }
14 | }
15 | }
16 |
17 | export function trimWhitespaceSsr(el, dir) {
18 | // This causes server<->client dom mismatches sometimes... gave up for now.
19 | /*
20 | for ( const node of (el.children || []) ) {
21 | if ( node.text ) {
22 | const trimmed = node.text.trim();
23 |
24 | if ( trimmed !== node.text ) {
25 | node.text = trimmed;
26 | }
27 | } else if ( node.children ) {
28 | trimWhitespaceSsr(node);
29 | }
30 | }
31 | */
32 | }
33 |
34 | Vue.directive('trim-whitespace', {
35 | inserted: trimWhitespace,
36 | componentUpdated: trimWhitespace,
37 | });
38 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/plugins/v-select.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import vSelect from 'vue-select';
3 |
4 | Vue.component('v-select', vSelect);
5 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/plugins/vue-js-modal.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import VModal from 'vue-js-modal';
3 |
4 | Vue.use(VModal);
5 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/preload/README.md:
--------------------------------------------------------------------------------
1 | # Preload Scripts
2 |
3 | This directory contains code exposed to the renderer as [preload scripts].
4 |
5 | [preload scripts]: https://www.electronjs.org/docs/latest/tutorial/tutorial-preload
6 |
7 | ## Extensions
8 |
9 | See https://docs.docker.com/desktop/extensions-sdk/ for details.
10 |
11 | e.g. splatform/epinio-docker-desktop
12 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/preload/index.ts:
--------------------------------------------------------------------------------
1 | import initExtensions from './extensions';
2 |
3 | function init() {
4 | initExtensions();
5 | }
6 |
7 | try {
8 | init();
9 | } catch (ex) {
10 | console.error(ex);
11 | throw ex;
12 | }
13 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/product.js:
--------------------------------------------------------------------------------
1 | export const NAME = 'rancher-desktop';
2 |
3 | export function init(plugin, store) {
4 | const { product } = plugin.DSL(store, NAME);
5 |
6 | product({
7 | inStore: 'management',
8 | icon: 'globe',
9 | label: 'Rancher Desktop',
10 | removable: false,
11 | showClusterSwitcher: false,
12 | category: 'global',
13 | to: { name: 'rancher-desktop-general' },
14 | });
15 | }
16 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/store/imageManager.js:
--------------------------------------------------------------------------------
1 | export const state = () => ({ imageManagerState: false });
2 |
3 | export const mutations = {
4 | SET_IMAGE_MANAGER_STATE(state, imageManagerState) {
5 | state.imageManagerState = imageManagerState;
6 | },
7 | };
8 |
9 | export const actions = {
10 | setImageManagerState({ commit }, imageManagerState) {
11 | commit('SET_IMAGE_MANAGER_STATE', imageManagerState);
12 | },
13 | };
14 |
15 | export const getters = {
16 | getImageManagerState({ imageManagerState }) {
17 | return imageManagerState;
18 | },
19 | };
20 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/store/k8sManager.js:
--------------------------------------------------------------------------------
1 | import { State as EngineStates } from '@pkg/backend/k8s';
2 | import { ipcRenderer } from '@pkg/utils/ipcRenderer';
3 |
4 | export const state = () => ({ k8sState: ipcRenderer.sendSync('k8s-state') });
5 |
6 | export const mutations = {
7 | SET_K8S_STATE(state, k8sState) {
8 | state.k8sState = k8sState;
9 | },
10 | };
11 |
12 | export const actions = {
13 | setK8sState({ commit }, k8sState) {
14 | commit('SET_K8S_STATE', k8sState);
15 | },
16 | };
17 |
18 | export const getters = {
19 | getK8sState({ k8sState }) {
20 | return k8sState;
21 | },
22 | isReady({ k8sState }) {
23 | return [EngineStates.STARTED, EngineStates.DISABLED].includes(k8sState);
24 | },
25 | };
26 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/store/ts-helpers.ts:
--------------------------------------------------------------------------------
1 | import type { UpperSnakeCase } from '@pkg/utils/typeUtils';
2 |
3 | import type { CommitOptions, Dispatch } from 'vuex';
4 |
5 | type MutationsPayloadType = {
6 | [key in keyof T as `SET_${ UpperSnakeCase }`]: T[key];
7 | };
8 |
9 | /**
10 | * MutationsType is used to describe the type that `mutations` should have.
11 | * This has a `SET_` method per property in `State`, that takes a payload of the
12 | * correct type.
13 | */
14 | export type MutationsType = {
15 | [key in keyof T as `SET_${ UpperSnakeCase }`]: (state: T, payload: T[key]) => any;
16 | };
17 |
18 | /**
19 | * ActionContext is the first argument for an action. We only declare the
20 | * subset we currently need. We're not using the types from Vuex as that does
21 | * not provide typing to match the mutations.
22 | */
23 | export type ActionContext = {
24 | commit>(
25 | type: mutationType,
26 | payload: MutationsPayloadType[mutationType],
27 | commitOptions?: CommitOptions): void;
28 | dispatch: Dispatch;
29 | state: T;
30 | rootState: any;
31 | getters: any;
32 | };
33 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/sudo-prompt/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Joran Dirk Greef
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/sudo-prompt/index.d.ts:
--------------------------------------------------------------------------------
1 | export function exec(cmd: string,
2 | options?: ((error?: Error, stdout?: string | Buffer, stderr?: string | Buffer) => void)
3 | | { name?: string, icns?: string, env?: { [key: string]: string } },
4 | callback?: (error?: Error, stdout?: string | Buffer, stderr?: string | Buffer) => void): void;
5 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/sudo-prompt/linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/pkg/rancher-desktop/sudo-prompt/linux.png
--------------------------------------------------------------------------------
/pkg/rancher-desktop/sudo-prompt/macos.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/pkg/rancher-desktop/sudo-prompt/macos.png
--------------------------------------------------------------------------------
/pkg/rancher-desktop/sudo-prompt/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sudo-prompt",
3 | "version": "9.2.1",
4 | "description": "Run a command using sudo, prompting the user with an OS dialog if necessary",
5 | "main": "index.js",
6 | "types": "index.d.ts",
7 | "files": [
8 | "LICENSE",
9 | "README.md",
10 | "index.d.ts",
11 | "index.js",
12 | "package.json",
13 | "test.js",
14 | "test-concurrent.js"
15 | ],
16 | "repository": {
17 | "type": "git",
18 | "url": "git+https://github.com/jorangreef/sudo-prompt.git"
19 | },
20 | "keywords": [
21 | "sudo",
22 | "os",
23 | "dialog",
24 | "prompt",
25 | "command",
26 | "exec",
27 | "user access control",
28 | "UAC",
29 | "privileges",
30 | "administrative",
31 | "elevate",
32 | "run as administrator"
33 | ],
34 | "author": "Joran Dirk Greef",
35 | "license": "MIT",
36 | "bugs": {
37 | "url": "https://github.com/jorangreef/sudo-prompt/issues"
38 | },
39 | "homepage": "https://github.com/jorangreef/sudo-prompt#readme",
40 | "scripts": {}
41 | }
42 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/sudo-prompt/test-concurrent.js:
--------------------------------------------------------------------------------
1 | import { exec } from 'child_process';
2 |
3 | import { exec as sudo } from './';
4 |
5 | function kill(end) {
6 | if (process.platform === 'win32') {
7 | return end();
8 | }
9 | exec('sudo -k', end);
10 | }
11 |
12 | kill(
13 | () => {
14 | const options = { name: 'Sudo Prompt' };
15 |
16 | let sleep;
17 |
18 | if (process.platform === 'win32') {
19 | sleep = 'timeout /t 10\r\necho world';
20 | } else {
21 | sleep = 'sleep 10 && echo world';
22 | }
23 | sudo(sleep, options,
24 | (error, stdout, stderr) => {
25 | console.log(error, stdout, stderr);
26 | },
27 | );
28 | sudo('echo hello', options,
29 | (error, stdout, stderr) => {
30 | console.log(error, stdout, stderr);
31 | },
32 | );
33 | },
34 | );
35 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/sudo-prompt/windows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/pkg/rancher-desktop/sudo-prompt/windows.png
--------------------------------------------------------------------------------
/pkg/rancher-desktop/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2018",
4 | "module": "ESNext",
5 | "moduleResolution": "Node",
6 | "lib": [
7 | "ESNext",
8 | "ESNext.AsyncIterable",
9 | "DOM"
10 | ],
11 | "esModuleInterop": true,
12 | "allowJs": true,
13 | "sourceMap": true,
14 | "strict": true,
15 | "noEmit": false,
16 | "experimentalDecorators": true,
17 | "baseUrl": ".",
18 | "paths": {
19 | "@pkg/*": [
20 | "./*"
21 | ]
22 | },
23 | "typeRoots": [
24 | "../../node_modules",
25 | "../../node_modules/@types",
26 | ],
27 | "types": [
28 | "@nuxt/types",
29 | "@types/node",
30 | "@types/jest"
31 | ]
32 | },
33 | "exclude": [
34 | "node_modules",
35 | ".nuxt",
36 | "dist",
37 | "babel.config.js"
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/typings/assets.d.ts:
--------------------------------------------------------------------------------
1 | declare module '@pkg/assets/*.yaml' {
2 | const content: any;
3 | export default content;
4 | }
5 |
6 | declare module '@pkg/assets/scripts/*' {
7 | const content: string;
8 | export default content;
9 | }
10 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/typings/linux-ca.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'linux-ca' {
2 | import * as forge from 'node-forge';
3 |
4 | export function getAllCerts(readSync?: boolean): Promise;
5 | export function getFilteredCerts(filterAttribute: string, filterMethod?: (cert: forge.pki.Certificate, attribute: string) => boolean): Promise;
6 | export function pemToCert(pem: string): forge.pki.Certificate;
7 | export function certToPem(cert: forge.pki.Certificate): string;
8 | export function defaultFilter(cert: forge.pki.Certificate, subject: string): boolean;
9 | }
10 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/typings/shell.d.ts:
--------------------------------------------------------------------------------
1 | declare module '@shell/core/types' {
2 | class IPlugin {
3 | metadata: any;
4 | addProduct: any;
5 | addRoutes: any;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/typings/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import Vue from 'vue';
3 | /* Load @nuxt/types, as a side effect it augments Vue */
4 | import {} from '@nuxt/types';
5 | export default Vue;
6 | }
7 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/typings/unix.interface.ts:
--------------------------------------------------------------------------------
1 | export interface UnixError {
2 | stdout: string;
3 | stderr: string;
4 | code: string;
5 | message: string;
6 | }
7 |
8 | export const isUnixError = (val: any): val is UnixError => {
9 | return 'stdout' in val &&
10 | 'stderr' in val &&
11 | 'code' in val &&
12 | 'message' in val;
13 | };
14 |
15 | export interface NodeError {
16 | syscall: string;
17 | path: string;
18 | code: string;
19 | message: string;
20 | errno: number;
21 | }
22 |
23 | export const isNodeError = (val: any): val is NodeError => {
24 | return 'syscall' in val &&
25 | 'path' in val &&
26 | 'code' in val &&
27 | 'message' in val;
28 | };
29 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/typings/vue-i18n.ts:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/no-unused-vars -- imported for side effect.
2 | import Vue from 'vue';
3 |
4 | // This is required to keep typescript from complaining. It is required for
5 | // our i18n plugin. For more info see:
6 | // https://v2.vuejs.org/v2/guide/typescript.html?redirect=true#Augmenting-Types-for-Use-with-Plugins
7 | declare module 'vue/types/vue' {
8 | interface Vue {
9 | /**
10 | * Lookup a given string with the given arguments
11 | * @param raw if set, do not do HTML escaping.
12 | */
13 | t: (key: string, args?: Record, raw?: boolean) => string,
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/DownloadProgressListener.ts:
--------------------------------------------------------------------------------
1 | import stream from 'stream';
2 |
3 | /**
4 | * DownloadProgressListener observes a stream pipe to monitor progress.
5 | */
6 | export default class DownloadProgressListener extends stream.Transform {
7 | protected status: { current: number };
8 |
9 | /**
10 | * Construct a new DownloadProgressListener, which will update the passed-in
11 | * object on progress. No events will be emitted to avoid redrawing the UI
12 | * too often; a timer/interval should be used instead.
13 | * @param status A object that will be modified when download progress occurs.
14 | * @param options Options to pass to {stream.Transform}.
15 | */
16 | constructor(status: { current: number }, options: stream.TransformOptions = {}) {
17 | super(options);
18 | this.status = status;
19 | }
20 |
21 | _transform(chunk: any, encoding: string, callback: stream.TransformCallback): void {
22 | if (encoding === 'buffer') {
23 | this.status.current += (chunk as Buffer).length;
24 | } else {
25 | this.status.current += (chunk as string).length;
26 | }
27 | callback(null, chunk);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/clone.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Clone a given object, returning a disconnected copy.
3 | *
4 | * @note This should be replaced via StructuredClone in NodeJS 18.
5 | * @note This only supports primitive objects (array, object, string, etc.)
6 | */
7 | export default function clone(input: T): T {
8 | return JSON.parse(JSON.stringify(input));
9 | }
10 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/dateUtils.ts:
--------------------------------------------------------------------------------
1 | import dayjs from 'dayjs';
2 |
3 | export function currentTime(): string {
4 | const date = dayjs(Date.now());
5 |
6 | return date.format('YYYY-MM-DD HH:mm');
7 | }
8 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/environment.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Checks if Rancher Desktop is running in a development or test environment
3 | * @returns True if Rancher Desktop is running in a development or test
4 | * environment
5 | */
6 | const isDev = /^(?:dev|test)/i.test(process.env.NODE_ENV || '');
7 | const isE2E = /^e2e/i.test(process.env.RD_TEST ?? '');
8 |
9 | export const isDevEnv = isDev || isE2E;
10 | export const isDevBuild = !isE2E && isDev;
11 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/filters.ts:
--------------------------------------------------------------------------------
1 | import { isArray } from './array';
2 |
3 | /**
4 | * Can be used to merge arrays of primitive data types in lodash.mergeWith() function
5 | *
6 | * @param {*} objValue first array
7 | * @param {*} srcValue second array
8 | * @returns always second array (incoming value)
9 | */
10 | export function arrayCustomizer(objValue: any, srcValue: any) {
11 | if (isArray(objValue) && objValue.every((i: any) => typeof i !== 'object')) {
12 | return srcValue;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/imageOutputCuller.js:
--------------------------------------------------------------------------------
1 | import ImageBuildOutputCuller from '@pkg/utils/processOutputInterpreters/image-build-output';
2 | import ImageNonBuildOutputCuller from '@pkg/utils/processOutputInterpreters/image-non-build-output';
3 | import TrivyScanImageOutputCuller from '@pkg/utils/processOutputInterpreters/trivy-image-output';
4 |
5 | const cullersByName = {
6 | build: ImageBuildOutputCuller,
7 | 'trivy-image': TrivyScanImageOutputCuller,
8 | };
9 |
10 | export default function getImageOutputCuller(command) {
11 | const klass = cullersByName[command] || ImageNonBuildOutputCuller;
12 |
13 | return new klass();
14 | }
15 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/latch.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Interface Latch is a simple extension on Promise that is resolved via calling
3 | * a method. It is essentially a simplified barrier.
4 | *
5 | * @see https://en.wikipedia.org/wiki/Barrier_(computer_science)
6 | */
7 | interface Latch extends Promise {
8 | /** Calling the resolve() method resolves the Latch. */
9 | resolve(): void;
10 | }
11 |
12 | /**
13 | * Creates a Latch that is an extension of a Promise that can be resolved via
14 | * calling a method on that Promise.
15 | */
16 | export default function Latch(): Latch {
17 | const holder: {resolve?: () => void} = {};
18 | const result: Latch = new Promise((resolve) => {
19 | holder.resolve = resolve;
20 | }) as any;
21 |
22 | if (!holder.resolve) {
23 | throw new Error('Promise created, but resolve function not set');
24 | }
25 | result.resolve = holder.resolve;
26 |
27 | return result;
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/networks.ts:
--------------------------------------------------------------------------------
1 | import os from 'os';
2 |
3 | export enum networkStatus {
4 | CHECKING = 'checking...',
5 | CONNECTED = 'online',
6 | OFFLINE = 'offline',
7 | }
8 |
9 | export function wslHostIPv4Address(): string | undefined {
10 | const interfaces = os.networkInterfaces();
11 | // The veth interface name changed at some time on Windows 11, so try the new name if the old one doesn't exist
12 | const iface = interfaces['vEthernet (WSL)'] ?? interfaces['vEthernet (WSL (Hyper-V firewall))'] ?? [];
13 |
14 | return iface.find(addr => addr.family === 'IPv4')?.address;
15 | }
16 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/osVersion.ts:
--------------------------------------------------------------------------------
1 | import * as process from 'process';
2 |
3 | import semver from 'semver';
4 |
5 | import { spawnFile } from '@pkg/utils/childProcess';
6 | import { Log } from '@pkg/utils/logging';
7 |
8 | let macOsVersion: semver.SemVer;
9 |
10 | export async function fetchMacOsVersion(console: Log) {
11 | let versionString = process.env.RD_MOCK_MACOS_VERSION;
12 |
13 | if (!versionString) {
14 | const { stdout } = await spawnFile('/usr/bin/sw_vers', ['-productVersion'], { stdio: ['ignore', 'pipe', console] });
15 |
16 | versionString = stdout.trimEnd();
17 | }
18 | const currentVersion = semver.coerce(versionString);
19 |
20 | if (currentVersion) {
21 | macOsVersion = currentVersion;
22 | } else {
23 | throw new Error(`Cannot convert "${ versionString }" to macOS semver`);
24 | }
25 | }
26 |
27 | export function getMacOsVersion(): semver.SemVer {
28 | return macOsVersion;
29 | }
30 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/processOutputInterpreters/__tests__/assets/trivy-image-metric-server-input.txt:
--------------------------------------------------------------------------------
1 | 2021-07-09T15:58:24.556-0700 [34mINFO[0m Detected OS: debian
2 | 2021-07-09T15:58:24.557-0700 [34mINFO[0m Detecting Debian vulnerabilities...
3 | 2021-07-09T15:58:24.559-0700 [34mINFO[0m Number of PL dependency files: 0
4 |
5 | rancher/metrics-server:v0.3.6 (debian 9.9)
6 | ==========================================
7 | Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)
8 |
9 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/processOutputInterpreters/__tests__/assets/trivy-image-metric-server-output.txt:
--------------------------------------------------------------------------------
1 | INFO Detected OS: debian
2 | INFO Detecting Debian vulnerabilities...
3 | INFO Number of PL dependency files: 0
4 |
5 | rancher/metrics-server:v0.3.6 (debian 9.9)
6 | ==========================================
7 | Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)
8 |
9 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/processOutputInterpreters/__tests__/image-build-output.spec.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import path from 'path';
3 |
4 | import ImageBuildOutputCuller from '@pkg/utils/processOutputInterpreters/image-build-output';
5 |
6 | describe('image build output', () => {
7 | it('returns the raw text back', () => {
8 | const buildOutputPath = path.join('./pkg/rancher-desktop/utils/processOutputInterpreters/__tests__/assets', 'build.txt');
9 | const data = fs.readFileSync(buildOutputPath).toString();
10 | const culler = new ImageBuildOutputCuller();
11 |
12 | culler.addData(data);
13 | expect(culler.getProcessedData()).toBe(data.replace(/\r/g, ''));
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/processOutputInterpreters/image-build-output.js:
--------------------------------------------------------------------------------
1 | const LineSplitter = /\r?\n/;
2 |
3 | export default class ImageBuildOutputCuller {
4 | constructor() {
5 | this.lines = [];
6 | }
7 |
8 | addData(data) {
9 | // TODO (possibly): Deal with partial final lines - I haven't seen this happen yet
10 | const lines = data.split(LineSplitter);
11 |
12 | this.lines.push(...lines);
13 | }
14 |
15 | getProcessedData() {
16 | return this.lines.join('\n');
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/string-encode.ts:
--------------------------------------------------------------------------------
1 | export const hexEncode = (str: string): string => Array.from(str)
2 | .map(c => `0${ c.charCodeAt(0).toString(16) }`.slice(-2))
3 | .join('');
4 |
5 | export const hexDecode = (hexString: string): string | undefined => hexString.match(/.{1,2}/g)
6 | ?.map(hex => String.fromCharCode(parseInt(hex, 16)))
7 | .join('');
8 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/stringify.ts:
--------------------------------------------------------------------------------
1 | export function jsonStringifyWithWhiteSpace(obj: Record): string {
2 | return `${ JSON.stringify(obj, undefined, 2) }\n`;
3 | }
4 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/testUtils/mockResources.ts:
--------------------------------------------------------------------------------
1 | // `Symbol.dispose` exists as of NodeJS 20; if it's unset, set it (because we
2 | // are currently on NodeJS 18).
3 | (Symbol as any).dispose ??= Symbol.for('nodejs.dispose');
4 |
5 | /**
6 | * Given a Jest SpyInstance, return it as a Disposable such that mockRestore will
7 | * be called when the instance goes out of scope.
8 | * @note This will no longer be needed as of Jest 30 (where it's built in).
9 | */
10 | export function withResource<
11 | T = any,
12 | Y extends any[] = any,
13 | C = any,
14 | U extends jest.MockInstance = any,
15 | >(input: U): U & Disposable {
16 | (input as any)[Symbol.dispose] = () => {
17 | input.mockRestore();
18 | };
19 |
20 | return input as U & Disposable;
21 | }
22 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/testUtils/setupElectron.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is preloaded into all Jest tests (see package.json,
3 | * `jest.setupFiles`) and is used to force-mock Electron as that does not work
4 | * inside Jest.
5 | */
6 |
7 | import path from 'path';
8 |
9 | if ('jest' in globalThis && 'mock' in jest) {
10 | jest.mock('electron', () => {
11 | return {
12 | __esModule: true,
13 | default: {
14 | app: {
15 | isPackaged: false,
16 | getAppPath: () => path.resolve('.'),
17 | },
18 | ipcMain: {},
19 | },
20 | };
21 | });
22 | }
23 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/utils/wslVersion.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This exports a single function to ask wsl-helper about the current WSL
3 | * version.
4 | */
5 |
6 | import { spawnFile } from '@pkg/utils/childProcess';
7 | import logging from '@pkg/utils/logging';
8 | import { executable } from '@pkg/utils/resources';
9 |
10 | export type WSLVersionInfo = {
11 | installed: boolean;
12 | inbox: boolean;
13 |
14 | has_kernel: boolean;
15 | outdated_kernel: boolean;
16 | version: {
17 | major: number;
18 | minor: number;
19 | build: number;
20 | revision: number;
21 | };
22 | kernel_version: {
23 | major: number;
24 | minor: number;
25 | build: number;
26 | revision: number;
27 | }
28 | };
29 |
30 | const console = logging['wsl-version'];
31 |
32 | /**
33 | * Get information about the currently installed WSL version.
34 | */
35 | export default async function getWSLVersion(): Promise {
36 | const { stdout } = await spawnFile(executable('wsl-helper'),
37 | ['wsl', 'info'], { stdio: ['ignore', 'pipe', console] });
38 |
39 | return JSON.parse(stdout);
40 | }
41 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/window/constants.ts:
--------------------------------------------------------------------------------
1 | export const mainRoutes = [
2 | { route: '/General' },
3 | { route: '/Containers', experimental: true },
4 | { route: '/PortForwarding' },
5 | { route: '/Images' },
6 | { route: '/Snapshots' },
7 | { route: '/Troubleshooting' },
8 | { route: '/Diagnostics' },
9 | { route: '/Extensions' },
10 | ];
11 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/window/dashboard.ts:
--------------------------------------------------------------------------------
1 | import { BrowserWindow } from 'electron';
2 |
3 | import { windowMapping, restoreWindow } from '.';
4 |
5 | const dashboardURL = 'http://127.0.0.1:6120/c/local/explorer';
6 |
7 | const getDashboardWindow = () => ('dashboard' in windowMapping) ? BrowserWindow.fromId(windowMapping['dashboard']) : null;
8 |
9 | export function openDashboard() {
10 | let window = getDashboardWindow();
11 |
12 | if (restoreWindow(window)) {
13 | return window;
14 | }
15 |
16 | window = new BrowserWindow({
17 | title: 'Rancher Dashboard',
18 | width: 800,
19 | height: 600,
20 | show: false,
21 | });
22 |
23 | window.loadURL(dashboardURL);
24 |
25 | windowMapping['dashboard'] = window.id;
26 |
27 | window.once('ready-to-show', () => {
28 | window?.show();
29 | });
30 | }
31 |
32 | export function closeDashboard() {
33 | getDashboardWindow()?.close();
34 | }
35 |
--------------------------------------------------------------------------------
/pkg/rancher-desktop/window/preferenceConstants.ts:
--------------------------------------------------------------------------------
1 | import { NavItemName } from '@pkg/config/transientSettings';
2 |
3 | interface NavItems {
4 | name: NavItemName;
5 | tabs?: string[];
6 | }
7 | const wslTabs: string[] = ['integrations', 'network', 'proxy'];
8 | const vmLinuxTabs: string[] = ['hardware', 'volumes'];
9 | const vmDarwinTabs: string[] = vmLinuxTabs.concat(['network', 'emulation']);
10 |
11 | export const preferencesNavItems: NavItems[] = [
12 | {
13 | name: 'Application',
14 | tabs: ['general', 'behavior', 'environment'],
15 | },
16 | {
17 | name: process.platform === 'win32' ? 'WSL' : 'Virtual Machine',
18 | tabs: process.platform === 'win32' ? wslTabs : ( process.platform === 'linux' ? vmLinuxTabs : vmDarwinTabs ),
19 | },
20 | {
21 | name: 'Container Engine',
22 | tabs: ['general', 'allowed-images'],
23 | },
24 | { name: 'Kubernetes' },
25 | ];
26 |
--------------------------------------------------------------------------------
/resources/darwin/bin/nerdctl:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -eu -o pipefail
3 |
4 | scriptname="${BASH_SOURCE[0]}"
5 | while [ -L "${scriptname}" ]; do
6 | scriptname="$(readlink "${scriptname}")"
7 | done
8 | scriptdir="$(cd "$(dirname "${scriptname}")" && pwd)"
9 |
10 | if ! LIMA_HOME="$HOME/Library/Application Support/rancher-desktop/lima" "${scriptdir}/../lima/bin/limactl" ls --json | grep '"name":"0"' | grep -q '"status":"Running"'; then
11 | echo "Rancher Desktop is not running. Please start Rancher Desktop to use nerdctl";
12 | exit 1
13 | else
14 | "${scriptdir}/rdctl" shell sudo --preserve-env=SSH_AUTH_SOCK nerdctl "$@"
15 | fi
16 |
--------------------------------------------------------------------------------
/resources/darwin/bin/spin:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -eu -o pipefail
3 |
4 | scriptname="${BASH_SOURCE[0]}"
5 | while [ -L "${scriptname}" ]; do
6 | scriptname=$(readlink "${scriptname}")
7 | done
8 | scriptdir=$(cd "$(dirname "${scriptname}")" && pwd)
9 | internal=$(cd "${scriptdir}/../internal" && pwd)
10 |
11 | export SPIN_DATA_DIR="$HOME/Library/Application Support/rancher-desktop/spin"
12 | mkdir -p "$SPIN_DATA_DIR"
13 | exec "${internal}/spin" "$@"
14 |
--------------------------------------------------------------------------------
/resources/icons/containerd-icon-color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/containerd-icon-color.png
--------------------------------------------------------------------------------
/resources/icons/issue-opened-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/issue-opened-16.png
--------------------------------------------------------------------------------
/resources/icons/issue-opened-16.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/issue-opened-16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/issue-opened-16@2x.png
--------------------------------------------------------------------------------
/resources/icons/kubernetes-icon-black-orig.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/kubernetes-icon-black-orig.png
--------------------------------------------------------------------------------
/resources/icons/kubernetes-icon-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/kubernetes-icon-black.png
--------------------------------------------------------------------------------
/resources/icons/kubernetes-icon-color-orig.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/kubernetes-icon-color-orig.png
--------------------------------------------------------------------------------
/resources/icons/kubernetes-icon-color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/kubernetes-icon-color.png
--------------------------------------------------------------------------------
/resources/icons/logo-square-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-square-512.png
--------------------------------------------------------------------------------
/resources/icons/logo-square-bw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-square-bw.png
--------------------------------------------------------------------------------
/resources/icons/logo-square-bw@1.25x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-square-bw@1.25x.png
--------------------------------------------------------------------------------
/resources/icons/logo-square-bw@1.5x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-square-bw@1.5x.png
--------------------------------------------------------------------------------
/resources/icons/logo-square-bw@2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-square-bw@2.png
--------------------------------------------------------------------------------
/resources/icons/logo-square-red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-square-red.png
--------------------------------------------------------------------------------
/resources/icons/logo-square-red@1.25x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-square-red@1.25x.png
--------------------------------------------------------------------------------
/resources/icons/logo-square-red@1.5x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-square-red@1.5x.png
--------------------------------------------------------------------------------
/resources/icons/logo-square-red@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-square-red@2x.png
--------------------------------------------------------------------------------
/resources/icons/logo-square.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-square.png
--------------------------------------------------------------------------------
/resources/icons/logo-square@1.25x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-square@1.25x.png
--------------------------------------------------------------------------------
/resources/icons/logo-square@1.5x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-square@1.5x.png
--------------------------------------------------------------------------------
/resources/icons/logo-square@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-square@2x.png
--------------------------------------------------------------------------------
/resources/icons/logo-tray-Template@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-tray-Template@2x.png
--------------------------------------------------------------------------------
/resources/icons/logo-tray-error-Template@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-tray-error-Template@2x.png
--------------------------------------------------------------------------------
/resources/icons/logo-tray-starting-Template@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-tray-starting-Template@2x.png
--------------------------------------------------------------------------------
/resources/icons/logo-tray-stopped-Template@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-tray-stopped-Template@2x.png
--------------------------------------------------------------------------------
/resources/icons/logo-tray-stopping-Template@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/logo-tray-stopping-Template@2x.png
--------------------------------------------------------------------------------
/resources/icons/mac-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/resources/icons/mac-icon.png
--------------------------------------------------------------------------------
/resources/linux/bin/nerdctl:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | if grep -q -i 'microsoft.*wsl' /proc/version; then
4 | exec /mnt/wsl/rancher-desktop/bin/nerdctl "$@"
5 | else
6 | limaloc="${XDG_DATA_HOME:-$HOME/.local/share}/rancher-desktop"
7 | scriptname="$0"
8 | while [ -L "${scriptname}" ]; do
9 | scriptname="$(readlink "${scriptname}")"
10 | done
11 | scriptdir="$(cd "$(dirname "${scriptname}")" && pwd)"
12 |
13 | if ! LIMA_HOME="${limaloc}/lima" "${scriptdir}/../lima/bin/limactl" ls --json | grep '"name":"0"' | grep -q '"status":"Running"'; then
14 | echo "Rancher Desktop is not running. Please start Rancher Desktop to use nerdctl";
15 | exit 1
16 | else
17 | "${scriptdir}/rdctl" shell sudo --preserve-env=SSH_AUTH_SOCK nerdctl "$@"
18 | fi
19 | fi
20 |
--------------------------------------------------------------------------------
/resources/linux/bin/spin:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -eu -o pipefail
3 |
4 | scriptname="${BASH_SOURCE[0]}"
5 | while [ -L "${scriptname}" ]; do
6 | scriptname=$(readlink "${scriptname}")
7 | done
8 | scriptdir=$(cd "$(dirname "${scriptname}")" && pwd)
9 | internal=$(cd "${scriptdir}/../internal" && pwd)
10 |
11 | export SPIN_DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/rancher-desktop/spin"
12 | mkdir -p "$SPIN_DATA_DIR"
13 | exec "${internal}/spin" "$@"
14 |
--------------------------------------------------------------------------------
/screenshots/extensions/logs-explorer-0.2.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rancher-sandbox/rancher-desktop/0216266849036b910dd0edd5c9f3c28a3424320e/screenshots/extensions/logs-explorer-0.2.2.png
--------------------------------------------------------------------------------
/screenshots/test-data/preferences.ts:
--------------------------------------------------------------------------------
1 | export const lockedSettings = {
2 | body: JSON.stringify({
3 | containerEngine: {
4 | allowedImages: {
5 | enabled: true,
6 | patterns: true,
7 | },
8 | },
9 | kubernetes: { version: true },
10 | }),
11 | status: 200,
12 | headers: {},
13 | };
14 |
--------------------------------------------------------------------------------
/screenshots/test-data/snapshots.ts:
--------------------------------------------------------------------------------
1 | import dayjs from 'dayjs';
2 |
3 | export const snapshotsList = {
4 | body: JSON.stringify([{
5 | name: 'Snapshot 1',
6 | created: dayjs(new Date(), 'YYYY-MM-DD_HH_mm_ss').subtract(5, 'minute'),
7 | }, {
8 | name: 'Snapshot 2',
9 | created: dayjs(new Date(), 'YYYY-MM-DD_HH_mm_ss'),
10 | }]),
11 | status: 200,
12 | headers: {},
13 | };
14 |
--------------------------------------------------------------------------------
/scripts/dependencies/sudo-prompt.ts:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 |
3 | import { Dependency, DownloadContext } from 'scripts/lib/dependencies';
4 | import { simpleSpawn } from 'scripts/simple_process';
5 |
6 | /**
7 | * SudoPrompt represents the sudo-prompt.app applet used by sudo-prompt on macOS.
8 | */
9 | export class SudoPrompt implements Dependency {
10 | readonly name = 'sudo-prompt';
11 |
12 | async download(_: DownloadContext): Promise {
13 | // Rather than actually downloading anything, this builds the source code.
14 | const sourceDir = path.join(process.cwd(), 'src', 'sudo-prompt');
15 |
16 | console.log(`Building sudo-prompt applet`);
17 | await simpleSpawn('./build-sudo-prompt', [], { cwd: sourceDir });
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/scripts/extension-data.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file generates pkg/rancher-desktop/assets/extension-data.yaml
3 | *
4 | * Usage: `yarn generate:extension-data`
5 | */
6 |
7 | import { generateExtensionMarketplaceData } from './lib/extension-data';
8 |
9 | generateExtensionMarketplaceData().catch((ex) => {
10 | console.error(ex);
11 | process.exit(1);
12 | });
13 |
--------------------------------------------------------------------------------
/scripts/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/rancher-sandbox/rancher-desktop/scripts
2 |
3 | go 1.23.0
4 |
5 | toolchain go1.23.4
6 |
7 | require golang.org/x/mod v0.24.0
8 |
--------------------------------------------------------------------------------
/scripts/go.sum:
--------------------------------------------------------------------------------
1 | golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
2 | golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
3 |
--------------------------------------------------------------------------------
/scripts/node-license-check.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit -o nounset -o pipefail
4 |
5 | # There is a single module with 0BSD license which is actually BSD-2-clause on GitHub
6 | ALLOWED="Apache-2.0|0?BSD|ISC|MIT|Python-2.0|Unlicense"
7 |
8 | # jq doesn't support \b word boundaries, so expand "\b(${ALLOWED})\b" into something supported
9 | REGEX="(^|[^a-zA-Z0-9_])(${ALLOWED})($|[^a-zA-Z0-9_])"
10 |
11 | JQ=".data.body[] | select(.[2] | test(\"${REGEX}\") | not)"
12 | FORBIDDEN=$(yarn licenses list --prod --json --no-progress | jq -r "$JQ")
13 |
14 | if [[ -z $FORBIDDEN ]]; then
15 | echo "All NPM modules have licenses matching ${ALLOWED}"
16 | exit 0
17 | fi
18 |
19 | echo "Forbidden license(s) detected; allowed are ${ALLOWED}"
20 | echo "$FORBIDDEN"
21 | exit 1
22 |
--------------------------------------------------------------------------------
/scripts/ts-wrapper.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This script is a wrapper to run TypeScript scripts via tsx. This is mostly
3 | * to set defaults for our tools, such as disabling BrowsersList updates and
4 | * showing deprecations.
5 | */
6 |
7 | const { spawnSync } = require('node:child_process');
8 |
9 | function main(args) {
10 | const childArgs = [
11 | '--trace-warnings',
12 | '--trace-deprecation',
13 | 'node_modules/tsx/dist/cli.mjs',
14 | '--conditions=import',
15 | ];
16 |
17 | const finalArgs = [...childArgs, ...args];
18 |
19 | console.log(process.argv0, ...finalArgs);
20 | const result = spawnSync(process.argv0, finalArgs, { stdio: 'inherit' });
21 |
22 | if (result.error) {
23 | throw result.error;
24 | }
25 |
26 | if (typeof result.status === 'number') {
27 | process.exit(result.status);
28 | }
29 |
30 | if (result.signal) {
31 | console.log(`Process exited with signal ${ result.signal }`);
32 | process.exit(-1);
33 | }
34 | }
35 |
36 | if (require.main === module) {
37 | // Silence BrowsersList warnings because they're pointless for us
38 | process.env.BROWSERSLIST_IGNORE_OLD_DATA = 'true'; // spellcheck-ignore-line
39 | main(process.argv.slice(2));
40 | }
41 |
--------------------------------------------------------------------------------
/scripts/windows/generate-nerdctl-stub.ps1:
--------------------------------------------------------------------------------
1 | # This script is executed on Windows to regenerate the nerdctl stub argument
2 | # parsers. This must be executed on Windows as we need a stable platform to be
3 | # able to find nerdctl.
4 |
5 | param(
6 | [switch]$Verbose
7 | )
8 |
9 | $ENV:GOOS = "linux"
10 |
11 | Set-Location src/go/nerdctl-stub/generate
12 | go build .
13 | wsl.exe -d rancher-desktop --exec ./generate "-verbose=$Verbose"
14 | Remove-Item ./generate
15 | gofmt -w ../nerdctl_commands_generated.go
16 |
--------------------------------------------------------------------------------
/scripts/windows/sudo-install-wsl.ps1:
--------------------------------------------------------------------------------
1 | # //////////////////////////////////////////////////////////////////////
2 | # sudo-install-ws1.ps1
3 |
4 | Param(
5 | [Parameter(Mandatory)]
6 | [ValidateSet("EnableWSL-01", "EnableVMPlatform-02", "InstallLinuxUpdatePackage-03")]
7 | $Step = "EnableWSL-01")
8 |
9 | $script = $myInvocation.MyCommand.Definition
10 | $scriptPath = Split-Path -parent $script
11 | . (Join-Path $scriptpath restart-helpers.ps1)
12 |
13 | try {
14 | Start-Process $psHome\powershell.exe -Verb Runas -ArgumentList "$ScriptPath/install-wsl.ps1 -Step $Step"
15 | } catch {
16 | echo "Something bad happened"
17 | pause
18 | }
19 |
--------------------------------------------------------------------------------
/scripts/windows/uninstall-wsl.ps1:
--------------------------------------------------------------------------------
1 | # //////////////////////////////////////////////////////////////////////
2 | # uninstall-wsl.ps1
3 |
4 | $script = $myInvocation.MyCommand.Definition
5 | $scriptPath = Split-Path -parent $script
6 | . (Join-Path $scriptpath restart-helpers.ps1)
7 |
8 | # Magic PowerShell comment to require admin; see
9 | # https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_requires?view=powershell-5.1#-runasadministrator
10 |
11 | #Requires -RunAsAdministrator
12 |
13 | wslconfig /u k3s
14 |
15 | Disable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -NoRestart
16 |
17 | Restart-Machine-On-Acceptance -Action "uninstall wsl"
18 |
--------------------------------------------------------------------------------
/scripts/wix.ts:
--------------------------------------------------------------------------------
1 | // This script builds the wix installer, assuming the zip file has already been
2 | // built (and dist/win-unpacked is populated).
3 | // This is only used during development.
4 |
5 | import fs from 'fs';
6 | import path from 'path';
7 |
8 | import buildInstaller, { buildCustomAction } from './lib/installer-win32';
9 |
10 | async function run() {
11 | const distDir = path.join(process.cwd(), 'dist');
12 | const appDir = path.join(distDir, 'win-unpacked');
13 |
14 | try {
15 | await fs.promises.access(path.join(appDir, 'resources', 'app.asar'), fs.constants.R_OK);
16 | } catch (ex) {
17 | if ((ex as NodeJS.ErrnoException).code !== 'ENOENT') {
18 | throw ex;
19 | }
20 | console.error(`Could not find ${ appDir }, please run \`yarn build\` first.`);
21 | process.exit(1);
22 | }
23 |
24 | const customActionFile = await buildCustomAction();
25 |
26 | await fs.promises.copyFile(customActionFile,
27 | path.join(appDir, path.basename(customActionFile)));
28 | await buildInstaller(distDir, appDir);
29 | }
30 |
31 | run().catch((ex) => {
32 | console.error(ex);
33 | process.exit(1);
34 | });
35 |
--------------------------------------------------------------------------------
/src/go/docker-credential-none/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/rancher-sandbox/rancher-desktop/src/go/docker-credential-none
2 |
3 | go 1.23.0
4 |
5 | toolchain go1.24.1
6 |
7 | require (
8 | github.com/docker/cli v28.2.2+incompatible
9 | github.com/docker/docker-credential-helpers v0.9.3
10 | )
11 |
12 | require (
13 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
14 | github.com/google/go-cmp v0.7.0 // indirect
15 | github.com/pkg/errors v0.9.1 // indirect
16 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
17 | github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af // indirect
18 | github.com/stretchr/testify v1.10.0 // indirect
19 | golang.org/x/sys v0.33.0 // indirect
20 | gotest.tools/v3 v3.5.1 // indirect
21 | )
22 |
--------------------------------------------------------------------------------
/src/go/docker-credential-none/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/docker/docker-credential-helpers/credentials"
5 |
6 | "github.com/rancher-sandbox/rancher-desktop/src/go/docker-credential-none/dcnone"
7 | )
8 |
9 | func main() {
10 | credentials.Serve(dcnone.DCNone{})
11 | }
12 |
--------------------------------------------------------------------------------
/src/go/extension-proxy/README.md:
--------------------------------------------------------------------------------
1 | # extension-proxy
2 |
3 | This program is used to forward HTTP requests from the extension frontend to the
4 | extension backend. The frontend makes a HTTP request using a relative URL
5 | (doing something like `ddClient.extension.vm.service.get('/foo')`), which must
6 | be routed to the backend listening on a Unix socket. This program is used to
7 | handle the forwarding from some TCP port into that Unix socket.
8 |
9 | The environment variable `SOCKET` should be set to the path of a Unix socket,
10 | which will be forwarded to port 80. Typically this would be set to the name of
11 | a socket in `/run/guest-services/`, which is then shared (via a volume) with
12 | other containers.
13 |
--------------------------------------------------------------------------------
/src/go/extension-proxy/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/rancher-sandbox/rancher-desktop/src/go/extension-port-forwarder
2 |
3 | go 1.22.0
4 |
--------------------------------------------------------------------------------
/src/go/guestagent/README.md:
--------------------------------------------------------------------------------
1 | [Rancher Desktop Guest Agent](/docs/networking/windows/rancher-desktop-guest-agent.md)
--------------------------------------------------------------------------------
/src/go/guestagent/pkg/forwarder/forwarder.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2024 SUSE LLC
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 | http://www.apache.org/licenses/LICENSE-2.0
7 | Unless required by applicable law or agreed to in writing, software
8 | distributed under the License is distributed on an "AS IS" BASIS,
9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | See the License for the specific language governing permissions and
11 | limitations under the License.
12 | */
13 |
14 | // Package forwarder implements a forwarding mechanism to forward
15 | // port mappings over the network.
16 | package forwarder
17 |
18 | import (
19 | "github.com/rancher-sandbox/rancher-desktop/src/go/guestagent/pkg/types"
20 | )
21 |
22 | // Forwarder is the interface that wraps the Send method which
23 | // to forward the port mappings.
24 | type Forwarder interface {
25 | // Send sends the give port mappings to the Peer via
26 | // a tcp connection.
27 | Send(portMapping types.PortMapping) error
28 | }
29 |
--------------------------------------------------------------------------------
/src/go/guestagent/pkg/kube/watcher_stub.go:
--------------------------------------------------------------------------------
1 | //go:build !linux
2 |
3 | /*
4 | Copyright © 2024 SUSE LLC
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | */
15 |
16 | package kube
17 |
18 | import (
19 | "context"
20 | "fmt"
21 | "net"
22 |
23 | "github.com/rancher-sandbox/rancher-desktop/src/go/guestagent/pkg/tracker"
24 | )
25 |
26 | func WatchForServices(
27 | ctx context.Context,
28 | configPath string,
29 | k8sServiceListenerIP net.IP,
30 | portTracker tracker.Tracker,
31 | ) error {
32 | return fmt.Errorf("not implemented for non-linux")
33 | }
34 |
--------------------------------------------------------------------------------
/src/go/guestagent/pkg/procnet/scanner_stub.go:
--------------------------------------------------------------------------------
1 | //go:build !linux
2 |
3 | /*
4 | Copyright © 2024 SUSE LLC
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | */
15 |
16 | package procnet
17 |
18 | import (
19 | "context"
20 | "fmt"
21 | "time"
22 |
23 | "github.com/rancher-sandbox/rancher-desktop/src/go/guestagent/pkg/tracker"
24 | )
25 |
26 | type ProcNetScanner struct{}
27 |
28 | func NewProcNetScanner(context.Context, tracker.Tracker, time.Duration) (*ProcNetScanner, error) {
29 | panic("only implemented for Linux")
30 | }
31 |
32 | func (p *ProcNetScanner) ForwardPorts() error {
33 | return fmt.Errorf("only implemented for Linux")
34 | }
35 |
--------------------------------------------------------------------------------
/src/go/mock-wsl/README.md:
--------------------------------------------------------------------------------
1 | # mock-wsl
2 |
3 | This is a mock `wsl.exe` that is used in the E2E tests, used to stub out
4 | interaction with the real WSL.
5 |
6 | ## Configuration
7 |
8 | The environment variable `RD_MOCK_WSL_DATA` should be set to the absolute path
9 | of a JSON file describing how the executable should act. This file will be
10 | modified as part of the run to contain the results and errors.
11 |
12 | Please see [`schema.json`](./schema.json) for the JSON schema for the file.
13 |
--------------------------------------------------------------------------------
/src/go/mock-wsl/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/rancher-sandbox/rancher-desktop/e2e/assets/mock-wsl
2 |
3 | go 1.23.0
4 |
5 | toolchain go1.23.4
6 |
7 | require (
8 | golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
9 | golang.org/x/sys v0.33.0
10 | golang.org/x/text v0.25.0
11 | )
12 |
--------------------------------------------------------------------------------
/src/go/mock-wsl/go.sum:
--------------------------------------------------------------------------------
1 | golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
2 | golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
3 | golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
4 | golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
5 | golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
6 | golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
7 |
--------------------------------------------------------------------------------
/src/go/mock-wsl/lock_file_other.go:
--------------------------------------------------------------------------------
1 | //go:build !windows
2 |
3 | /*
4 | Copyright © 2024 SUSE LLC
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 | package main
20 |
21 | import (
22 | "fmt"
23 | "os"
24 | )
25 |
26 | func lockFile(_ *os.File) error {
27 | return fmt.Errorf("not implemented")
28 | }
29 |
--------------------------------------------------------------------------------
/src/go/mock-wsl/lock_file_windows.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "math"
6 | "os"
7 |
8 | "golang.org/x/sys/windows"
9 | )
10 |
11 | // lockFile locks the given file for exclusive access; if the file is already
12 | // locked, this function will wait until it is unlocked.
13 | func lockFile(f *os.File) error {
14 | err := windows.LockFileEx(
15 | windows.Handle(f.Fd()),
16 | windows.LOCKFILE_EXCLUSIVE_LOCK,
17 | 0,
18 | math.MaxUint32, math.MaxUint32,
19 | &windows.Overlapped{})
20 | if err != nil {
21 | return fmt.Errorf("failed to lock file: %w", err)
22 | }
23 | return nil
24 | }
25 |
--------------------------------------------------------------------------------
/src/go/nerdctl-stub/README.md:
--------------------------------------------------------------------------------
1 | # nerdctl-stub
2 |
3 | This is a stub executable used to launch nerdctl on Windows (and WSL).
4 |
5 | ## Usage
6 |
7 | Use like normal nerdctl, except that some things can be controlled via
8 | environment variables:
9 |
10 | Variable | Meaning | Default
11 | --- | --- | ---
12 | RD_WSL_DISTRO | WSL distribution to run in | `rancher-desktop`
13 | RD_NERDCTL | `nerdctl` executable | `/usr/local/bin/nerdctl`
14 |
--------------------------------------------------------------------------------
/src/go/nerdctl-stub/debugging_stub.go:
--------------------------------------------------------------------------------
1 | //go:build !debug
2 |
3 | /*
4 | Copyright © 2024 SUSE LLC
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 | package main
20 |
21 | // describeCommands is a debugging function that prints out all commands.
22 | // This implementation is a stub that does nothing.
23 | func describeCommands() {
24 | }
25 |
--------------------------------------------------------------------------------
/src/go/nerdctl-stub/generate/README.md:
--------------------------------------------------------------------------------
1 | # nerdctl-sub/generate
2 |
3 | This directory contains a tool that generates the argument parser for
4 | nerdctl-stub (by parsing the output of `nerdctl -help`).
5 |
6 | ## Usage
7 |
8 | ```powershell
9 | yarn generate:nerdctl-stub
10 | ```
11 |
--------------------------------------------------------------------------------
/src/go/nerdctl-stub/generate/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/rancher-sandbox/rancher-desktop/src/go/nerdctl-stub/generate
2 |
3 | go 1.23.0
4 |
5 | toolchain go1.23.4
6 |
7 | require github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af
8 |
9 | require (
10 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
11 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
12 | github.com/stretchr/testify v1.10.0 // indirect
13 | golang.org/x/sys v0.33.0 // indirect
14 | )
15 |
--------------------------------------------------------------------------------
/src/go/nerdctl-stub/generate/main_stub.go:
--------------------------------------------------------------------------------
1 | //go:build !linux
2 |
3 | package main
4 |
5 | import (
6 | "log"
7 | )
8 |
9 | func main() {
10 | log.Fatal("nerdctl-stub generate needs to be done on Linux")
11 | }
12 |
--------------------------------------------------------------------------------
/src/go/nerdctl-stub/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/rancher-sandbox/rancher-desktop/src/go/nerdctl-stub
2 |
3 | go 1.23.0
4 |
5 | toolchain go1.23.4
6 |
7 | require (
8 | github.com/hashicorp/go-multierror v1.1.1
9 | github.com/stretchr/testify v1.10.0
10 | golang.org/x/sys v0.33.0
11 | )
12 |
13 | require (
14 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
15 | github.com/hashicorp/errwrap v1.1.0 // indirect
16 | github.com/kr/pretty v0.3.1 // indirect
17 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
18 | github.com/rogpeppe/go-internal v1.13.1 // indirect
19 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
20 | gopkg.in/yaml.v3 v3.0.1 // indirect
21 | )
22 |
--------------------------------------------------------------------------------
/src/go/networking/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | capture.pcap
3 | tmp/
4 | *.exe
5 |
--------------------------------------------------------------------------------
/src/go/networking/Makefile:
--------------------------------------------------------------------------------
1 | LDFLAGS = -ldflags '-s -w'
2 |
3 | .PHONY: build
4 | build: host-switch vm-switch network-setup wsl-proxy
5 |
6 | bin/host-switch.exe:
7 | GOOS=windows go build $(LDFLAGS) -o $@ ./cmd/host
8 |
9 | .PHONY: host-switch
10 | host-switch: bin/host-switch.exe
11 |
12 | bin/vm-switch:
13 | GOOS=linux go build $(LDFLAGS) -o $@ ./cmd/vm
14 |
15 | .PHONY: vm-switch
16 | vm-switch: bin/vm-switch
17 |
18 | bin/network-setup:
19 | GOOS=linux go build $(LDFLAGS) -o $@ ./cmd/network
20 |
21 | .PHONY: network-setup
22 | network-setup: bin/network-setup
23 |
24 | bin/wsl-proxy:
25 | GOOS=linux go build $(LDFLAGS) -o $@ ./cmd/proxy
26 |
27 | .PHONY: wsl-proxy
28 | wsl-proxy: bin/wsl-proxy
29 |
30 | .PHONY: fmt
31 | fmt:
32 | gofmt -l -s -w .
33 |
34 | .PHONY: clean
35 | clean:
36 | rm -rf ./bin
37 |
38 | .PHONY: vendor
39 | vendor:
40 | go mod tidy
41 | go mod vendor
42 |
--------------------------------------------------------------------------------
/src/go/networking/pkg/log/log.go:
--------------------------------------------------------------------------------
1 | package log
2 |
3 | /*
4 | Copyright © 2023 SUSE LLC
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | */
15 |
16 | import (
17 | "os"
18 |
19 | "github.com/sirupsen/logrus"
20 | )
21 |
22 | const fileMode = 0o666
23 |
24 | // SetOutputFile sets the logger output with a given file
25 | func SetOutputFile(filePath string, logger *logrus.Logger) error {
26 | logFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fileMode)
27 | if err != nil {
28 | return err
29 | }
30 | logger.SetOutput(logFile)
31 |
32 | return nil
33 | }
34 |
--------------------------------------------------------------------------------
/src/go/networking/pkg/vsock/conn_windows.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2024 SUSE LLC
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 | http://www.apache.org/licenses/LICENSE-2.0
7 | Unless required by applicable law or agreed to in writing, software
8 | distributed under the License is distributed on an "AS IS" BASIS,
9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | See the License for the specific language governing permissions and
11 | limitations under the License.
12 | */
13 |
14 | package vsock
15 |
16 | import (
17 | "fmt"
18 | "net"
19 |
20 | "github.com/Microsoft/go-winio"
21 | "github.com/linuxkit/virtsock/pkg/hvsock"
22 | )
23 |
24 | func Listen(vmGUID hvsock.GUID, vsockPort uint32) (net.Listener, error) {
25 | svcPort, err := hvsock.GUIDFromString(winio.VsockServiceID(vsockPort).String())
26 | if err != nil {
27 | return nil, fmt.Errorf("Listen, could not parse Hyper-v service GUID: %v", err)
28 | }
29 |
30 | addr := hvsock.Addr{
31 | VMID: vmGUID,
32 | ServiceID: svcPort,
33 | }
34 |
35 | return hvsock.Listen(addr)
36 | }
37 |
--------------------------------------------------------------------------------
/src/go/networking/pkg/vsock/constants.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2023 SUSE LLC
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 | http://www.apache.org/licenses/LICENSE-2.0
7 | Unless required by applicable law or agreed to in writing, software
8 | distributed under the License is distributed on an "AS IS" BASIS,
9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | See the License for the specific language governing permissions and
11 | limitations under the License.
12 | */
13 |
14 | package vsock
15 |
16 | const (
17 | SignaturePhrase = "github.com/rancher-sandbox/rancher-desktop/src/go/networking"
18 | ReadySignal = "READY"
19 | )
20 |
--------------------------------------------------------------------------------
/src/go/rdctl/README.md:
--------------------------------------------------------------------------------
1 | # rdctl
2 |
3 | This is the command-line interface (CLI) for Rancher Desktop.
4 |
5 | ## Prerequisites
6 |
7 | This tool depends on code generated during `yarn postinstall`.
8 |
9 | ## Usage
10 |
11 | Run `rdctl --help` for usage information.
12 |
13 | Much of `rdctl`'s functionality depends on the HTTP server running within Rancher Desktop,
14 | but some functionality is available when it isn't running, in particular the
15 | `rdctl factory-reset` command, which can be used to remove files generated by Rancher Desktop,
16 | those required for its functionality, and state files, such as a VM snapshot.
17 |
--------------------------------------------------------------------------------
/src/go/rdctl/cmd/paths.go:
--------------------------------------------------------------------------------
1 | package cmd
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "os"
7 |
8 | "github.com/spf13/cobra"
9 |
10 | p "github.com/rancher-sandbox/rancher-desktop/src/go/rdctl/pkg/paths"
11 | )
12 |
13 | var pathsCmd = &cobra.Command{
14 | Hidden: true,
15 | Use: "paths",
16 | Short: "Print the paths to directories that Rancher Desktop uses",
17 | RunE: func(cmd *cobra.Command, args []string) error {
18 | paths, err := p.GetPaths()
19 | if err != nil {
20 | return fmt.Errorf("failed to construct Paths: %w", err)
21 | }
22 | encoder := json.NewEncoder(os.Stdout)
23 | err = encoder.Encode(paths)
24 | if err != nil {
25 | return fmt.Errorf("failed to output paths: %w", err)
26 | }
27 | return nil
28 | },
29 | }
30 |
31 | func init() {
32 | rootCmd.AddCommand(pathsCmd)
33 | }
34 |
--------------------------------------------------------------------------------
/src/go/rdctl/cmd/setup.go:
--------------------------------------------------------------------------------
1 | package cmd
2 |
3 | import (
4 | "errors"
5 |
6 | "github.com/spf13/cobra"
7 |
8 | "github.com/rancher-sandbox/rancher-desktop/src/go/rdctl/pkg/autostart"
9 | )
10 |
11 | var setupSettings struct {
12 | AutoStart bool
13 | }
14 |
15 | var setupCmd = &cobra.Command{
16 | Hidden: true,
17 | Use: "setup",
18 | Short: "Configure the system without modifying settings",
19 | RunE: func(cmd *cobra.Command, args []string) error {
20 | if cmd.Flags().Changed("auto-start") {
21 | return autostart.EnsureAutostart(cmd.Context(), setupSettings.AutoStart)
22 | }
23 | return errors.New("no changes were specified")
24 | },
25 | }
26 |
27 | func init() {
28 | rootCmd.AddCommand(setupCmd)
29 | setupCmd.Flags().BoolVar(&setupSettings.AutoStart, "auto-start", false, "Whether to start Rancher Desktop at login")
30 | }
31 |
--------------------------------------------------------------------------------
/src/go/rdctl/cmd/snapshotDelete.go:
--------------------------------------------------------------------------------
1 | package cmd
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/spf13/cobra"
7 |
8 | "github.com/rancher-sandbox/rancher-desktop/src/go/rdctl/pkg/snapshot"
9 | )
10 |
11 | var snapshotDeleteCmd = &cobra.Command{
12 | Use: "delete ",
13 | Short: "Delete a snapshot",
14 | Args: cobra.ExactArgs(1),
15 | RunE: func(cmd *cobra.Command, args []string) error {
16 | cmd.SilenceUsage = true
17 | err := deleteSnapshot(cmd, args)
18 | return exitWithJSONOrErrorCondition(err)
19 | },
20 | }
21 |
22 | func init() {
23 | snapshotCmd.AddCommand(snapshotDeleteCmd)
24 | snapshotDeleteCmd.Flags().BoolVarP(&outputJSONFormat, "json", "", false, "output json format")
25 | }
26 |
27 | func deleteSnapshot(_ *cobra.Command, args []string) error {
28 | manager, err := snapshot.NewManager()
29 | if err != nil {
30 | return fmt.Errorf("failed to create snapshot manager: %w", err)
31 | }
32 | if err = manager.Delete(args[0]); err != nil {
33 | return fmt.Errorf("failed to delete snapshot %q: %w", args[0], err)
34 | }
35 | return nil
36 | }
37 |
--------------------------------------------------------------------------------
/src/go/rdctl/main.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2022 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package main
18 |
19 | import (
20 | "github.com/rancher-sandbox/rancher-desktop/src/go/rdctl/cmd"
21 | )
22 |
23 | func main() {
24 | cmd.Execute()
25 | }
26 |
--------------------------------------------------------------------------------
/src/go/rdctl/pkg/client/handle_unix.go:
--------------------------------------------------------------------------------
1 | //go:build unix
2 |
3 | package client
4 |
5 | import (
6 | "errors"
7 |
8 | "golang.org/x/sys/unix"
9 | )
10 |
11 | func handleConnectionRefused(err error) error {
12 | if errors.Is(err, unix.ECONNREFUSED) {
13 | return ErrConnectionRefused
14 | }
15 | return err
16 | }
17 |
--------------------------------------------------------------------------------
/src/go/rdctl/pkg/client/handle_windows.go:
--------------------------------------------------------------------------------
1 | package client
2 |
3 | import (
4 | "errors"
5 |
6 | "golang.org/x/sys/windows"
7 | )
8 |
9 | func handleConnectionRefused(err error) error {
10 | if errors.Is(err, windows.WSAECONNREFUSED) {
11 | return ErrConnectionRefused
12 | }
13 | return err
14 | }
15 |
--------------------------------------------------------------------------------
/src/go/rdctl/pkg/directories/empty.go:
--------------------------------------------------------------------------------
1 | //go:build !windows
2 |
3 | /*
4 | Copyright © 2022 SUSE LLC
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 | package directories
20 |
21 | import "fmt"
22 |
23 | func GetLocalAppDataDirectory() (string, error) {
24 | return "", fmt.Errorf("internal error: GetLocalAppDataDirectory shouldn't be called")
25 | }
26 |
27 | func GetRoamingAppDataDirectory() (string, error) {
28 | return "", fmt.Errorf("internal error: GetRoamingAppDataDirectory shouldn't be called")
29 | }
30 |
--------------------------------------------------------------------------------
/src/go/rdctl/pkg/factoryreset/factory_reset_unix.go:
--------------------------------------------------------------------------------
1 | //go:build unix
2 |
3 | /*
4 | Copyright © 2022 SUSE LLC
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 | package factoryreset
20 |
21 | import (
22 | "context"
23 | "fmt"
24 | )
25 |
26 | func CheckProcessWindows() (bool, error) {
27 | return false, fmt.Errorf("internal error: CheckProcessWindows shouldn't be called")
28 | }
29 |
30 | func KillRancherDesktop(ctx context.Context) error {
31 | return fmt.Errorf("internal error: KillRancherDesktop shouldn't be called")
32 | }
33 |
--------------------------------------------------------------------------------
/src/go/rdctl/pkg/lima/name.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2025 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | // Package lima contains the constants related to running Rancher Desktop using
18 | // lima (i.e. darwin / Linux).
19 | package lima
20 |
21 | const (
22 | // The name of the lima instance, without the `lima-` prefix.
23 | InstanceName = "0"
24 | // The name of the lima instance, including the `lima-` prefix.
25 | InstanceFullName = "lima-" + InstanceName
26 | )
27 |
--------------------------------------------------------------------------------
/src/go/rdctl/pkg/lock/mock.go:
--------------------------------------------------------------------------------
1 | package lock
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/rancher-sandbox/rancher-desktop/src/go/rdctl/pkg/paths"
7 | )
8 |
9 | type MockBackendLock struct {
10 | }
11 |
12 | func (lock *MockBackendLock) Lock(ctx context.Context, appPaths *paths.Paths, action string) error {
13 | return nil
14 | }
15 |
16 | func (lock *MockBackendLock) Unlock(ctx context.Context, appPaths *paths.Paths, restart bool) error {
17 | return nil
18 | }
19 |
--------------------------------------------------------------------------------
/src/go/rdctl/pkg/options/generated/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2024 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | // Package options contains the generated options.
18 | package options
19 |
20 | // This file exists so that dependabot can find the package; the actual options
21 | // are generated via `yarn postinstall`.
22 |
--------------------------------------------------------------------------------
/src/go/rdctl/pkg/paths/paths_test.go:
--------------------------------------------------------------------------------
1 | package paths
2 |
3 | import (
4 | "path/filepath"
5 | "runtime"
6 | "testing"
7 |
8 | "github.com/stretchr/testify/assert"
9 | )
10 |
11 | const fakeResourcesPath = "fakePath"
12 |
13 | func mockGetResourcesPath() (string, error) {
14 | return fakeResourcesPath, nil
15 | }
16 |
17 | func TestGetResourcesPath(t *testing.T) {
18 | dir := t.TempDir()
19 | rdctlPathOverride = filepath.Join(dir, "resources", runtime.GOOS, "bin", "rdctl")
20 | actual, err := GetResourcesPath()
21 | if assert.NoError(t, err) {
22 | assert.Equal(t, filepath.Join(dir, "resources"), actual)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/go/rdctl/pkg/process/process_test.go:
--------------------------------------------------------------------------------
1 | package process_test
2 |
3 | import (
4 | "os"
5 | "testing"
6 |
7 | "github.com/stretchr/testify/assert"
8 | "github.com/stretchr/testify/require"
9 |
10 | "github.com/rancher-sandbox/rancher-desktop/src/go/rdctl/pkg/process"
11 | )
12 |
13 | func TestFindPidOfProcess(t *testing.T) {
14 | exe, err := os.Executable()
15 | require.NoError(t, err)
16 | pid, err := process.FindPidOfProcess(exe)
17 | require.NoError(t, err)
18 | assert.Equal(t, os.Getpid(), pid)
19 | }
20 |
--------------------------------------------------------------------------------
/src/go/rdctl/pkg/process/process_windows_test.go:
--------------------------------------------------------------------------------
1 | package process
2 |
3 | import (
4 | "strings"
5 | "testing"
6 |
7 | "github.com/stretchr/testify/assert"
8 | "github.com/stretchr/testify/require"
9 | "golang.org/x/sys/windows"
10 | )
11 |
12 | func TestBuildCommandLine(t *testing.T) {
13 | t.Parallel()
14 | cases := [][]string{
15 | {"arg0", "a b c", "d", "e"},
16 | {"C:\\Program Files\\arg0\\\\", "ab\"c", "\\", "d"},
17 | {"\\\\", "a\\\\\\b", "de fg", "h"},
18 | {"arg0", "a\\\"b", "c", "d"},
19 | {"arg0", "a\\\\b c", "d", "e"},
20 | {"arg0", "ab\" c d"},
21 | {"C:/Path\\with/mixed slashes"},
22 | {"arg0", " leading", " and ", "trailing ", "space"},
23 | {"special characters", "&", "|", ">", "<", "*", "\"", " "},
24 | }
25 | for _, testcase := range cases {
26 | t.Run(strings.Join(testcase, " "), func(t *testing.T) {
27 | t.Parallel()
28 | result := buildCommandLine(testcase)
29 | argv, err := windows.DecomposeCommandLine(result)
30 | require.NoError(t, err, "failed to parse result %s", result)
31 | assert.Equal(t, testcase, argv, "failed to round trip arguments via [%s]", result)
32 | })
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/go/rdctl/pkg/snapshot/snapshot.go:
--------------------------------------------------------------------------------
1 | package snapshot
2 |
3 | import (
4 | "encoding/json"
5 | "time"
6 | )
7 |
8 | type Snapshot struct {
9 | Created time.Time `json:"created"`
10 | Name string `json:"name"`
11 | ID string `json:"id,omitempty"`
12 | Description string `json:"description"`
13 | }
14 |
15 | func (s *Snapshot) getTimeString() string {
16 | return s.Created.Format(time.RFC3339)
17 | }
18 |
19 | func (s *Snapshot) MarshalJSON() ([]byte, error) {
20 | type Alias Snapshot
21 | return json.Marshal(&struct {
22 | *Alias
23 | Created string `json:"created"`
24 | }{
25 | Alias: (*Alias)(s),
26 | Created: s.getTimeString(),
27 | })
28 | }
29 |
--------------------------------------------------------------------------------
/src/go/rdctl/pkg/snapshot/snapshotter.go:
--------------------------------------------------------------------------------
1 | package snapshot
2 |
3 | import (
4 | "context"
5 | "errors"
6 |
7 | "github.com/rancher-sandbox/rancher-desktop/src/go/rdctl/pkg/paths"
8 | )
9 |
10 | // Types that implement Snapshotter are responsible for copying/creating
11 | // files that need to be copied/created for the creation and restoration of
12 | // snapshots.
13 | type Snapshotter interface {
14 | // Does all of the things that can fail when creating a snapshot,
15 | // so that the snapshot creation can easily be rolled back upon
16 | // a failure.
17 | CreateFiles(ctx context.Context, appPaths *paths.Paths, snapshotDir string) error
18 | // Like CreateFiles, but for restoring: does all of the things
19 | // that can fail when restoring a snapshot so that restoration can
20 | // easily be rolled back in the event of a failure. Returns ErrDataReset
21 | // when data has been reset due to an error in this process.
22 | RestoreFiles(ctx context.Context, appPaths *paths.Paths, snapshotDir string) error
23 | }
24 |
25 | // Returned by Snapshotter.RestoreFiles when data has been reset
26 | // due to an error restoring the files.
27 | var ErrDataReset = errors.New("data reset")
28 |
--------------------------------------------------------------------------------
/src/go/rdctl/pkg/version/version.go:
--------------------------------------------------------------------------------
1 | package version
2 |
3 | var Version = "0.0.0"
4 |
--------------------------------------------------------------------------------
/src/go/rdctl/pkg/wsl/doc.go:
--------------------------------------------------------------------------------
1 | // Package wsl defines an interface, and implements types, that wrap
2 | // the WSL command line. As of the time of writing, the main purpose
3 | // of this type is to ease testing.
4 | package wsl
5 |
--------------------------------------------------------------------------------
/src/go/rdctl/pkg/wsl/mock_windows.go:
--------------------------------------------------------------------------------
1 | package wsl
2 |
3 | type MockWSL struct{}
4 |
5 | func (wsl MockWSL) UnregisterDistros() error {
6 | return nil
7 | }
8 |
9 | func (wsl MockWSL) ExportDistro(distroName, fileName string) error {
10 | return nil
11 | }
12 |
13 | func (wsl MockWSL) ImportDistro(distroName, installLocation, fileName string) error {
14 | return nil
15 | }
16 |
--------------------------------------------------------------------------------
/src/go/rdctl/pkg/wsl/names.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2025 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package wsl
18 |
19 | const (
20 | // The name of the WSL distribution (when not using lima).
21 | DistributionName = "rancher-desktop"
22 | // The name of the WSL data distribution (when not using lima).
23 | DataDistributionName = DistributionName + "-data"
24 | )
25 |
--------------------------------------------------------------------------------
/src/go/spin-stub/README.md:
--------------------------------------------------------------------------------
1 | # spin-stub
2 |
3 | This is a stub executable used to launch spin on Windows.
4 |
5 | ## Usage
6 |
7 | Use it as you would with a normal `spin` command. It simply configures the `SPIN_DATA_DIR` environment variable to point to the spin subdirectory within the Rancher Desktop application data directory, and then runs `../internal/spin.exe` (relative to the location of the `spin-stub` binary).
8 |
--------------------------------------------------------------------------------
/src/go/spin-stub/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/rancher-sandbox/rancher-desktop/src/go/spin-stub
2 |
3 | go 1.22.0
4 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/.gitignore:
--------------------------------------------------------------------------------
1 | /pkg/dockerproxy/models/
2 | /pkg/dockerproxy/swagger.yaml
3 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/cmd/dockerproxy.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2021 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package cmd
18 |
19 | import (
20 | "github.com/spf13/cobra"
21 | )
22 |
23 | // dockerproxyStartCmd is the `wsl-helper docker-proxy` command.
24 | // It only has subcommands, and no functionality of its own.
25 | var dockerproxyCmd = &cobra.Command{
26 | Use: "docker-proxy",
27 | Short: "Commands for managing the docker socket proxy",
28 | }
29 |
30 | func init() {
31 | rootCmd.AddCommand(dockerproxyCmd)
32 | }
33 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/cmd/k3s.go:
--------------------------------------------------------------------------------
1 | //go:build linux
2 |
3 | /*
4 | Copyright © 2021 SUSE LLC
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 | package cmd
20 |
21 | import (
22 | "github.com/spf13/cobra"
23 | )
24 |
25 | // k3sCmd represents the k3s command
26 | var k3sCmd = &cobra.Command{
27 | Use: "k3s",
28 | Short: "Commands for interacting with k3s in WSL",
29 | }
30 |
31 | func init() {
32 | rootCmd.AddCommand(k3sCmd)
33 | }
34 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/cmd/process_windows.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2024 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package cmd
18 |
19 | import (
20 | "github.com/spf13/cobra"
21 | )
22 |
23 | // processCmd represents the `wsl-helper process ...` subcommand
24 | var processCmd = &cobra.Command{
25 | Use: "process",
26 | Short: "Commands for managing processes on Windows",
27 | Hidden: true,
28 | }
29 |
30 | func init() {
31 | rootCmd.AddCommand(processCmd)
32 | }
33 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/cmd/wsl.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2023 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package cmd
18 |
19 | import (
20 | "github.com/spf13/cobra"
21 | )
22 |
23 | // k3sCmd represents the k3s command
24 | var wslCmd = &cobra.Command{
25 | Use: "wsl",
26 | Short: "Commands for interacting with WSL",
27 | Hidden: true,
28 | }
29 |
30 | func init() {
31 | rootCmd.AddCommand(wslCmd)
32 | }
33 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/cmd/wsl_integration_linux.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2023 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package cmd
18 |
19 | import (
20 | "github.com/spf13/cobra"
21 | )
22 |
23 | // wslIntegrationCmd represents the `wsl integration` command
24 | var wslIntegrationCmd = &cobra.Command{
25 | Use: "integration",
26 | Short: "Commands for managing with WSL integration",
27 | }
28 |
29 | func init() {
30 | wslCmd.AddCommand(wslIntegrationCmd)
31 | }
32 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/main.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2021 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package main
17 |
18 | import "github.com/rancher-sandbox/rancher-desktop/src/go/wsl-helper/cmd"
19 |
20 | func main() {
21 | cmd.Execute()
22 | }
23 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/pkg/dockerproxy/defaults.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2021 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package dockerproxy
18 |
19 | // DefaultPort is the default (vsock) port we're listening on.
20 | const DefaultPort = 23752375
21 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/pkg/dockerproxy/generate.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2021 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package dockerproxy
18 |
19 | import (
20 | _ "github.com/go-swagger/go-swagger"
21 | )
22 |
23 | //go:generate -command swagger go run github.com/go-swagger/go-swagger/cmd/swagger@v0.30.5
24 | //go:generate swagger generate server --quiet --skip-validation --config-file swagger-configuration.yaml --server-package models --spec swagger.yaml
25 |
26 | func init() {
27 | }
28 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/pkg/dockerproxy/models/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2024 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | // Package models contains the auto-generated OpenAPI models.
18 | package models
19 |
20 | // These imports exist so that dependabot is aware we use them.
21 | import (
22 | _ "github.com/go-openapi/errors"
23 | _ "github.com/go-openapi/strfmt" // spellcheck-ignore-line
24 | _ "github.com/go-openapi/swag"
25 | _ "github.com/go-openapi/validate"
26 | )
27 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/pkg/dockerproxy/mungers/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2021 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | // Package mungers includes the code to modify each moby API.
18 | package mungers
19 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/pkg/dockerproxy/swagger-configuration.yaml:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 SUSE LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # This is a go-swagger configuration file to generate the models for moby from
16 | # its OpenAPI specification.
17 |
18 | layout:
19 | models:
20 | - name: definition
21 | source: asset:model
22 | target: "{{ joinFilePath .Target .ModelPackage }}"
23 | file_name: "{{ pascalize .Name | snakize }}.go"
24 | application:
25 | - name: embedded_spec
26 | source: asset:swaggerJsonEmbed
27 | target: "{{ joinFilePath .Target (toPackagePath .ServerPackage) }}"
28 | file_name: "embedded_spec.go"
29 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/pkg/process/imports_windows.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2023 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package process
18 |
19 | import "golang.org/x/sys/windows"
20 |
21 | var (
22 | kernel32Dll = windows.NewLazySystemDLL("kernel32.dll")
23 | openProcess = kernel32Dll.NewProc("OpenProcess")
24 | attachConsole = kernel32Dll.NewProc("AttachConsole")
25 | freeConsole = kernel32Dll.NewProc("FreeConsole")
26 | setConsoleCtrlHandler = kernel32Dll.NewProc("SetConsoleCtrlHandler")
27 | )
28 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/pkg/process/run_windows.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2023 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package process
18 |
19 | import (
20 | "fmt"
21 | "os/exec"
22 | )
23 |
24 | func Launch(executable string, args ...string) error {
25 | err := exec.Command(executable, args...).Start()
26 | if err != nil {
27 | return fmt.Errorf("failed to start %s: %w", executable, err)
28 | }
29 | return nil
30 | }
31 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/pkg/version/version.go:
--------------------------------------------------------------------------------
1 | package version
2 |
3 | var Version = "0.0.0"
4 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/pkg/wsl-utils/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2023 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | // Package wslutils retrieves information about WSL.
18 | package wslutils
19 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/wix/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2023 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | // Package main implements a Windows Installer custom action DLL. That is, it
18 | // exports functions using CGO that will be called by Windows Installer.
19 | package main
20 |
--------------------------------------------------------------------------------
/src/go/wsl-helper/wix/imports_windows.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2023 SUSE LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package main
18 |
19 | import "golang.org/x/sys/windows"
20 |
21 | type MSIHANDLE uint32
22 |
23 | var (
24 | dllMsi = windows.NewLazySystemDLL("msi.dll")
25 | msiCloseHandle = dllMsi.NewProc("MsiCloseHandle")
26 | msiCreateRecord = dllMsi.NewProc("MsiCreateRecord")
27 | msiRecordSetStringW = dllMsi.NewProc("MsiRecordSetStringW")
28 | msiProcessMessage = dllMsi.NewProc("MsiProcessMessage")
29 | msiSetPropertyW = dllMsi.NewProc("MsiSetPropertyW")
30 | )
31 |
--------------------------------------------------------------------------------
/src/sudo-prompt/build-sudo-prompt:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # shellcheck disable=SC2164 # Use 'cd ... || exit' or 'cd ... || return' in case cd fails.
4 | REPO=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.."; pwd)
5 |
6 | # The APP name must be "Rancher Desktop.app" because this name is used in the dialog as
7 | # "Rancher Desktop wants to make changes."
8 | RESOURCES="${REPO}/resources"
9 | APP="${RESOURCES}/darwin/internal/Rancher Desktop.app"
10 | CONTENTS="${APP}/Contents"
11 |
12 | rm -rf "$APP"
13 | mkdir -p "$(dirname "$APP")"
14 | osacompile -o "$APP" sudo-prompt.applescript
15 |
16 | # Don't put the script into ${CONTENTS}/MacOS/ because that breaks signing the applet
17 | cp sudo-prompt-script "${CONTENTS}/Resources/Scripts/"
18 | sips -s format icns "${RESOURCES}/icons/mac-icon.png" --out "${CONTENTS}/Resources/applet.icns"
19 |
20 | plutil -replace CFBundleName -string "Rancher Desktop Password Prompt" "${CONTENTS}/Info.plist"
21 |
--------------------------------------------------------------------------------
/src/sudo-prompt/sudo-prompt-script:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # This script is executed by the applet with root permissions.
3 | # The caller will have created a temporary directory containing just the
4 | # `sudo-prompt-command` shell script. This script will add the `code`,
5 | # `stdout` and `stderr` files. The caller will delete this directory
6 | # again after reading the files.
7 |
8 | # Set sudo timestamp for subsequent sudo calls if tty_tickets are disabled:
9 | /bin/mkdir -p /var/db/sudo/$USER > /dev/null 2>&1
10 | /usr/bin/touch /var/db/sudo/$USER > /dev/null 2>&1
11 | # AppleScript's "do shell script" may alter stdout line-endings.
12 | # It may also set stdout to stderr if there was a non-zero return code and no stderr.
13 | # We therefore prefer to redirect output streams and capture return code manually:
14 | /bin/bash sudo-prompt-command 1>stdout 2>stderr
15 | /bin/echo $? > code
16 | # Correct ownership of stdout, stderr and code so that user can delete them:
17 | /usr/sbin/chown $USER stdout stderr code
18 | # Always return 0 so that AppleScript does not show error dialog:
19 | exit 0
20 |
--------------------------------------------------------------------------------
/src/sudo-prompt/sudo-prompt.applescript:
--------------------------------------------------------------------------------
1 | set appletPath to POSIX path of (path to me)
2 | if appletPath ends with ".app/" then
3 | set appletPath to appletPath & "Contents/Resources/Scripts"
4 | else
5 | set appletPath to do shell script "dirname " & quoted form of appletPath
6 | end if
7 | set promptScript to appletPath & "/sudo-prompt-script"
8 | do shell script (quoted form of promptScript) with administrator privileges
9 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2018",
4 | "module": "ESNext",
5 | "moduleResolution": "Node",
6 | "jsx": "react",
7 | "lib": [
8 | "ESNext",
9 | "ESNext.AsyncIterable",
10 | "DOM"
11 | ],
12 | "esModuleInterop": true,
13 | "allowJs": true,
14 | "sourceMap": true,
15 | "strict": true,
16 | "experimentalDecorators": true,
17 | "baseUrl": ".",
18 | "paths": {
19 | "@pkg/*": [
20 | "pkg/rancher-desktop/*"
21 | ],
22 | "@shell/*": [
23 | "./node_modules/@rancher/shell/*"
24 | ]
25 | },
26 | "typeRoots": [
27 | "./node_modules",
28 | "./node_modules/@types",
29 | "./node_modules/@rancher/shell/types"
30 | ],
31 | "types": [
32 | "@types/node",
33 | "@types/jest"
34 | ]
35 | },
36 | "exclude": [
37 | "node_modules",
38 | ".nuxt",
39 | "dist",
40 | "scripts/lib/installer-*.tsx",
41 | "scripts/lib/installer-win32-gen.tsx"
42 | ],
43 | "include": [
44 | "**/*",
45 | "**/*.ts",
46 | "**/*.d.ts",
47 | "**/*.tsx",
48 | "**/*.vue",
49 | ".eslintrc.js"
50 | ]
51 | }
52 |
--------------------------------------------------------------------------------