Skip to content

Commit 95a2b90

Browse files
authored
Merge pull request #8304 from mook-as/rdx/marketplace/data-cleanup
RDX: Simplify marketplace
2 parents b2ee4e0 + c550bb2 commit 95a2b90

File tree

12 files changed

+587
-2205
lines changed

12 files changed

+587
-2205
lines changed

.github/actions/spelling/excludes.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,12 @@
9393
ignore$
9494
/translations/(?!en)
9595
^\Qpkg/rancher-desktop/router.js\E$
96-
^\Qpkg/rancher-desktop/utils/_demo_marketplace_items.js\E$
97-
^\Qpkg/rancher-desktop/utils/_demo_metadata.js\E$
9896
(?:^|/)pkg/rancher-desktop/nuxt/
9997
^\Qsrc/disk-images/github-runner-linux/root/etc/sysconfig/network/ifcfg-\E
10098
^\Qsrc/go/nerdctl-stub/nerdctl_commands_generated.go\E$
10199
^\Q.github/workflows/config/.golangci.yaml\E$
102100
^\Qsrc/go/networking/.golangci.yml\E$
101+
# Generated file
102+
^\Qpkg/rancher-desktop/assets/extension-data.yaml\E$
103+
# Mostly image names
104+
^\Qscripts/assets/extension-data.yaml\E$

.github/actions/spelling/patterns.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,6 @@ regexp?\.MustCompile\(`[^`]*`\)
177177

178178
# allow repetitive words in iptable rules
179179
DNAT\s+.*\s+anywhere anywhere
180+
181+
# Image names
182+
\bghcr\.io/[A-Za-z0-9_/.-]+(?::[A-Za-z0-9_.-]+)?\b

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"lint:go:nofix": "node scripts/ts-wrapper.js scripts/lint-go.ts",
2727
"lint:spelling": "bash scripts/spelling.sh",
2828
"generate:nerdctl-stub": "powershell scripts/windows/generate-nerdctl-stub.ps1",
29+
"generate:extension-data": "node scripts/ts-wrapper.js scripts/extension-data.ts",
2930
"build": "cross-env NODE_OPTIONS=--max_old_space_size=4096 node --stack-size=16384 scripts/ts-wrapper.js scripts/build.ts",
3031
"package": "node scripts/ts-wrapper.js scripts/package.ts",
3132
"sign": "node scripts/ts-wrapper.js scripts/sign.ts",

pkg/rancher-desktop/assets/extension-data.yaml

Lines changed: 440 additions & 0 deletions
Large diffs are not rendered by default.

pkg/rancher-desktop/components/MarketplaceCard.vue

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
<div class="extensions-card">
44
<div class="extensions-card-header">
55
<img
6-
:src="extension.logo_url.small"
6+
:src="extension.logo"
77
alt=""
88
/>
99
<div class="extensions-card-header-top">
10-
<span class="extensions-card-header-title">{{ extension.name }}</span>
10+
<span class="extensions-card-header-title">{{ extension.title }}</span>
1111
<span class="extensions-card-header-subtitle">{{
12-
extension.publisher.name
12+
extension.publisher
1313
}}</span>
1414
</div>
1515
</div>
@@ -54,18 +54,19 @@
5454
</div>
5555
</template>
5656

57-
<script>
58-
57+
<script lang="ts">
5958
import { Banner } from '@rancher/components';
6059
6160
import LoadingIndicator from '@pkg/components/LoadingIndicator.vue';
62-
import demoMetadata from '@pkg/utils/_demo_metadata.js';
61+
import { MarketplaceData } from '@pkg/store/extensions.js';
62+
63+
import type { PropType } from 'vue';
6364
6465
export default {
6566
components: { LoadingIndicator, Banner },
6667
props: {
6768
extension: {
68-
type: Object,
69+
type: Object as PropType<MarketplaceData>,
6970
required: true,
7071
},
7172
credentials: {
@@ -79,27 +80,26 @@ export default {
7980
},
8081
data() {
8182
return {
82-
loading: false,
83-
extensionDetails: null,
84-
error: null,
85-
response: null,
86-
bannerActive: false,
83+
loading: false,
84+
error: null as string | null,
85+
response: null,
86+
bannerActive: false,
8787
};
8888
},
8989
computed: {
9090
installationAction() {
9191
return this.isInstalled ? 'uninstall' : 'install';
9292
},
9393
versionedExtension() {
94-
return `${ this.extensionWithoutVersion }:${ this.extensionDetails?.version }`;
94+
return `${ this.extensionWithoutVersion }:${ this.extension.version }`;
9595
},
9696
extensionWithoutVersion() {
9797
const index = this.extension.slug.lastIndexOf(':');
9898
9999
return this.extension.slug.substring(0, index) || this.extension.slug;
100100
},
101101
extensionLink() {
102-
return this.extension.slug.includes('ghcr.io') ? `https://${ this.extension.slug }` : `https://hub.docker.com/extensions/${ this.extension.slug }`;
102+
return this.extension.slug.startsWith('ghcr.io/') ? `https://${ this.extension.slug }` : `https://hub.docker.com/extensions/${ this.extension.slug }`;
103103
},
104104
buttonLabel() {
105105
if (this.loading) {
@@ -110,25 +110,11 @@ export default {
110110
},
111111
},
112112
113-
mounted() {
114-
this.metadata = demoMetadata[this.extensionWithoutVersion];
115-
116-
if (!this.metadata) {
117-
return;
118-
}
119-
120-
this.extensionDetails = {
121-
name:
122-
this.metadata?.LatestVersion.Labels['org.opencontainers.image.title'] ||
123-
this.extensionWithoutVersion,
124-
version: this.metadata?.LatestVersion.Tag || [],
125-
};
126-
},
127113
methods: {
128114
resetBanners() {
129115
this.error = null;
130116
},
131-
appInstallation(action) {
117+
appInstallation(action: 'uninstall' | 'install') {
132118
this.loading = true;
133119
this.resetBanners();
134120
const extensionId = action === 'uninstall' ? this.extensionWithoutVersion : this.versionedExtension;

pkg/rancher-desktop/components/MarketplaceCatalog.vue

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
<script lang="ts">
2+
import semver from 'semver';
23
import Vue, { VueConstructor } from 'vue';
34
import { mapGetters } from 'vuex';
45
5-
import { demoMarketplace } from '../utils/_demo_marketplace_items.js';
6-
76
import MarketplaceCard from '@pkg/components/MarketplaceCard.vue';
87
import { Settings, ContainerEngine } from '@pkg/config/settings';
9-
import { ExtensionState } from '@pkg/store/extensions.js';
10-
11-
type FilteredExtensions = typeof demoMarketplace.summaries;
8+
import { ExtensionState, MarketplaceData } from '@pkg/store/extensions.js';
129
13-
interface installedExtensions extends ExtensionState {
14-
id: string
15-
}
10+
type ExtensionData = MarketplaceData & { installed: boolean };
1611
1712
interface VuexBindings {
1813
getPreferences: Settings;
@@ -30,8 +25,6 @@ export default (Vue as VueConstructor<Vue & VuexBindings>).extend({
3025
password: '',
3126
port: 0,
3227
},
33-
extensions: demoMarketplace.summaries,
34-
installedExtensions: [] as installedExtensions[],
3528
};
3629
},
3730
async fetch() {
@@ -47,6 +40,10 @@ export default (Vue as VueConstructor<Vue & VuexBindings>).extend({
4740
},
4841
computed: {
4942
...mapGetters('preferences', ['getPreferences']),
43+
...mapGetters('extensions', { installedExtensions: 'list', extensions: 'marketData' }) as {
44+
installedExtensions: () => ({ id: string } & ExtensionState )[],
45+
extensions: () => MarketplaceData[],
46+
},
5047
containerEngine(): string {
5148
return this.getPreferences.containerEngine.name;
5249
},
@@ -59,28 +56,21 @@ export default (Vue as VueConstructor<Vue & VuexBindings>).extend({
5956
allowedExtensions(): string[] {
6057
return this.getPreferences.application.extensions.allowed.list;
6158
},
62-
filteredExtensions(): FilteredExtensions {
59+
filteredExtensions(): ExtensionData[] {
6360
let tempExtensions = this.extensions
6461
.filter((item) => {
6562
return this.isAllowed(item.slug);
6663
})
6764
.map((item) => {
68-
if (this.isInstalled(item.slug)) {
69-
return {
70-
...item,
71-
installed: true,
72-
};
73-
}
74-
7565
return {
7666
...item,
77-
installed: false,
67+
installed: this.isInstalled(item.slug),
7868
};
7969
});
8070
8171
if (this.searchValue) {
8272
tempExtensions = tempExtensions.filter((item) => {
83-
return item.name
73+
return item.title
8474
.toLowerCase()
8575
.includes(this.searchValue.toLowerCase());
8676
});
@@ -89,15 +79,19 @@ export default (Vue as VueConstructor<Vue & VuexBindings>).extend({
8979
const collator = new Intl.Collator('en', { sensitivity: 'base' });
9080
9181
return filteredExtensions.sort((s1, s2) => {
92-
return collator.compare(s1.name, s2.name);
82+
return collator.compare(s1.title, s2.title);
9383
});
9484
},
9585
},
9686
methods: {
9787
isInstalled(slug: string) {
98-
this.installedExtensions = this.$store.getters['extensions/list'];
88+
return !!this.installedExtensions.find(item => item?.id === slug);
89+
},
90+
isOutdated(slug: string) {
91+
const available = this.extensions.find(item => item.slug === slug);
92+
const installed = this.installedExtensions.find(item => item?.id === slug);
9993
100-
return this.installedExtensions.find(item => item?.id === slug);
94+
return available && installed && semver.gt(available.version, installed.version);
10195
},
10296
isAllowed(slug: string) {
10397
return !this.allowedListEnabled || this.allowedExtensions.includes(slug);
@@ -130,7 +124,7 @@ export default (Vue as VueConstructor<Vue & VuexBindings>).extend({
130124
>
131125
<MarketplaceCard
132126
:extension="item"
133-
:data-test="`extension-card-${item.name.toLowerCase()}`"
127+
:data-test="`extension-card-${item.title.toLowerCase()}`"
134128
:is-installed="item.installed"
135129
:credentials="credentials"
136130
@update:extension="isInstalled"

pkg/rancher-desktop/main/extensions/manager.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ import {
1111
Extension, ExtensionErrorCode, ExtensionManager, SpawnOptions, SpawnResult,
1212
} from './types';
1313

14+
import MARKETPLACE_DATA from '@pkg/assets/extension-data.yaml';
1415
import type { ContainerEngineClient } from '@pkg/backend/containerClient';
1516
import { ContainerEngine, Settings } from '@pkg/config/settings';
1617
import { getIpcMainProxy } from '@pkg/main/ipcMain';
1718
import mainEvents from '@pkg/main/mainEvents';
1819
import type { IpcMainEvents, IpcMainInvokeEvents, IpcRendererEvents } from '@pkg/typings/electron-ipc';
19-
import { demoMarketplace } from '@pkg/utils/_demo_marketplace_items';
2020
import { parseImageReference } from '@pkg/utils/dockerUtils';
2121
import fetch, { RequestInit } from '@pkg/utils/fetch';
2222
import Logging from '@pkg/utils/logging';
@@ -318,7 +318,7 @@ export class ExtensionManagerImpl implements ExtensionManager {
318318
if (!this.#supportedExtensions) {
319319
const supported: Record<string, boolean> = {};
320320

321-
for (const item of demoMarketplace.summaries) {
321+
for (const item of MARKETPLACE_DATA) {
322322
const slug = parseImageReference(item.slug);
323323

324324
if (!slug) {

pkg/rancher-desktop/store/extensions.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { GetterTree } from 'vuex';
33
import { fetchAPI } from './credentials';
44
import { ActionContext, MutationsType } from './ts-helpers';
55

6+
import MARKETPLACE_DATA from '@pkg/assets/extension-data.yaml';
67
import type { ExtensionMetadata } from '@pkg/main/extensions/types';
78

89
export interface ExtensionState {
@@ -15,6 +16,17 @@ interface ExtensionsState {
1516
extensions: Record<string, ExtensionState>;
1617
}
1718

19+
export interface MarketplaceData {
20+
slug: string;
21+
version: string;
22+
containerd_compatible: boolean;
23+
labels: Record<string, string>;
24+
title: string;
25+
logo: string;
26+
publisher: string;
27+
short_description: string;
28+
}
29+
1830
export const state: () => ExtensionsState = () => ({ extensions: {} });
1931

2032
export const mutations: MutationsType<ExtensionsState> = {
@@ -44,4 +56,7 @@ export const getters: GetterTree<ExtensionsState, ExtensionsState> = {
4456
list(state: ExtensionsState): ({ id: string } & ExtensionState )[] {
4557
return Object.entries(state.extensions).map(([id, info]) => ({ id, ...info }));
4658
},
59+
marketData(state: ExtensionsState): MarketplaceData[] {
60+
return MARKETPLACE_DATA;
61+
},
4762
};

0 commit comments

Comments
 (0)