From f66410ebcbf86bde806b4a60441d5d573d2758d0 Mon Sep 17 00:00:00 2001 From: Abhijeet <41686026+abhvsn@users.noreply.github.com> Date: Thu, 6 Apr 2023 23:15:03 +0530 Subject: [PATCH] feat: Add functionality to opt out plugin from airgap instance (#22098) ## Description As a part of supporting airgap instances we want to restrict the plugins which have any public dependency. This PR introduces a config setting for plugins to opt out of airgap. Also as a part of this exercise we are also adding a setting for CS dependency which can be utilised in future if our customers wants to opt out of CS dependent plugins. Corresponding EE PR: https://github.com/appsmithorg/appsmith-ee/pull/1258 > TL;DR: Provide a way for plugins supported in Appsmith to opt-out of airgap instances Fixes https://github.com/appsmithorg/appsmith/issues/21499 ## Type of change - New feature (non-breaking change which adds functionality) ## How Has This Been Tested? - Manual ## Checklist: ### Dev activity - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes ### QA activity: - [ ] Test plan has been approved by relevant developers - [ ] Test plan has been peer reviewed by QA - [ ] Cypress test cases have been added and approved by either SDET or manual QA - [ ] Organized project review call with relevant stakeholders after Round 1/2 of QA - [ ] Added Test Plan Approved label after reveiwing all Cypress test --- .../external/constants/PluginConstants.java | 14 +++++ .../com/appsmith/server/domains/Plugin.java | 10 +++ ...n005OptOutUnsupportedPluginsForAirGap.java | 62 +++++++++++++++++++ .../PluginCodeContributionsGuidelines.md | 9 +++ 4 files changed, 95 insertions(+) create mode 100644 app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/PluginConstants.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration005OptOutUnsupportedPluginsForAirGap.java diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/PluginConstants.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/PluginConstants.java new file mode 100644 index 0000000000..bc67040cf0 --- /dev/null +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/PluginConstants.java @@ -0,0 +1,14 @@ +package com.appsmith.external.constants; + +public interface PluginConstants { + + interface PackageName { + String SAAS_PLUGIN = "saas-plugin"; + String RAPID_API_PLUGIN = "rapidapi-plugin"; + String FIRESTORE_PLUGIN = "firestore-plugin"; + String REDSHIFT_PLUGIN = "redshift-plugin"; + String DYNAMO_PLUGIN = "dynamo-plugin"; + String AMAZON_S3_PLUGIN = "amazons3-plugin"; + String GOOGLE_SHEETS_PLUGIN = "google-sheets-plugin"; + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Plugin.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Plugin.java index 90015a2388..4138aedc2a 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Plugin.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Plugin.java @@ -107,4 +107,14 @@ public class Plugin extends BaseDomain { @JsonView(Views.Public.class) Map templates; + // Field to distinguish if the plugin is supported in air-gap instance, by default all the plugins will be supported. + // One can opt out by adding this field in DB object. Generally SaaS plugins and DB which can't be self-hosted can + // be a candidate for opting out of air-gap + @JsonView(Views.Internal.class) + boolean isSupportedForAirGap = true; + + // Config to set if the plugin has any dependency on cloud-services + @JsonView(Views.Internal.class) + Boolean isDependentOnCS; + } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration005OptOutUnsupportedPluginsForAirGap.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration005OptOutUnsupportedPluginsForAirGap.java new file mode 100644 index 0000000000..b1b38bef03 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration005OptOutUnsupportedPluginsForAirGap.java @@ -0,0 +1,62 @@ +package com.appsmith.server.migrations.db.ce; + +import com.appsmith.external.models.PluginType; +import com.appsmith.server.domains.Plugin; +import io.mongock.api.annotations.ChangeUnit; +import io.mongock.api.annotations.Execution; +import io.mongock.api.annotations.RollbackExecution; +import org.springframework.data.mongodb.core.MongoTemplate; + +import java.util.List; +import java.util.Set; + +import static com.appsmith.external.constants.PluginConstants.PackageName.AMAZON_S3_PLUGIN; +import static com.appsmith.external.constants.PluginConstants.PackageName.DYNAMO_PLUGIN; +import static com.appsmith.external.constants.PluginConstants.PackageName.FIRESTORE_PLUGIN; +import static com.appsmith.external.constants.PluginConstants.PackageName.GOOGLE_SHEETS_PLUGIN; +import static com.appsmith.external.constants.PluginConstants.PackageName.RAPID_API_PLUGIN; +import static com.appsmith.external.constants.PluginConstants.PackageName.REDSHIFT_PLUGIN; +import static com.appsmith.external.constants.PluginConstants.PackageName.SAAS_PLUGIN; + +@ChangeUnit(order = "005", id="opt-out-unsupported-plugins-airgap-instance", author = " ") +public class Migration005OptOutUnsupportedPluginsForAirGap { + + private final MongoTemplate mongoTemplate; + + public Migration005OptOutUnsupportedPluginsForAirGap(MongoTemplate mongoTemplate) { + this.mongoTemplate = mongoTemplate; + } + + @RollbackExecution + public void rollBackExecution() { + } + + @Execution + public void optOutUnsupportedPluginsForAirGapInstance() { + // By default, all the plugins will be supported in air-gap instance. + // One can opt out the support for plugin by adding `isSupportedForAirGap:false` in DB object. + // Generally SaaS plugins and DBs which can't be self-hosted can be a candidate for opting out of air-gap as + // these are dependent on external internet + final Set unsupportedPluginPackageNameInAirgap = Set.of( + SAAS_PLUGIN, RAPID_API_PLUGIN, FIRESTORE_PLUGIN, REDSHIFT_PLUGIN, DYNAMO_PLUGIN, + AMAZON_S3_PLUGIN, GOOGLE_SHEETS_PLUGIN + ); + + final Set cloudServicesDependentPluginTypes = Set.of(PluginType.SAAS, PluginType.REMOTE); + + List plugins = mongoTemplate.findAll(Plugin.class); + for (Plugin plugin : plugins) { + if (unsupportedPluginPackageNameInAirgap.contains(plugin.getPackageName()) + || cloudServicesDependentPluginTypes.contains(plugin.getType())) { + + if (unsupportedPluginPackageNameInAirgap.contains(plugin.getPackageName())) { + plugin.setSupportedForAirGap(false); + } + if (cloudServicesDependentPluginTypes.contains(plugin.getType())) { + plugin.setIsDependentOnCS(true); + } + mongoTemplate.save(plugin); + } + } + } +} diff --git a/contributions/ServerCodeContributionsGuidelines/PluginCodeContributionsGuidelines.md b/contributions/ServerCodeContributionsGuidelines/PluginCodeContributionsGuidelines.md index 9c19bb9c2c..50aee71e8e 100644 --- a/contributions/ServerCodeContributionsGuidelines/PluginCodeContributionsGuidelines.md +++ b/contributions/ServerCodeContributionsGuidelines/PluginCodeContributionsGuidelines.md @@ -178,6 +178,15 @@ The `BasePlugin` & `PluginExecutor` classes define the basic operations of plugi plugin.setIconLocation("https://your-plugin-icon-location.png"); plugin.setDocumentationLink("https://link-to-plugin-documentation.html"); plugin.setDefaultInstall(true); + + // Field to distinguish if the plugin is supported in air-gap instance, by default all the plugins will be + // supported. One can opt out by adding this field in DB object. Generally SaaS plugins and DB which can't be + // self-hosted can be a candidate for opting out of air-gap + plugin.setSupportedForAirGap(false); + + // Config to set if the plugin has any dependency on cloud-services + plugin.setIsDependentOnCS(true); + try { mongoTemplate.insert(plugin); } catch (DuplicateKeyException e) {