diff --git a/assets/keycloak/README.md b/assets/keycloak/README.md
new file mode 100644
index 0000000..595283d
--- /dev/null
+++ b/assets/keycloak/README.md
@@ -0,0 +1,7 @@
+# Adding themes to keycloak
+
+When running the keycloak container, please mount `providers` folder to `/opt/keycloak/providers`.
+
+`opea` login theme will then be available under admin panel login theme.
+
+the `realm-export.json` will automatically configured the client with the login theme.
\ No newline at end of file
diff --git a/assets/keycloak/data/import/genaistudio-realm.json b/assets/keycloak/data/import/genaistudio-realm.json
new file mode 100644
index 0000000..d3e13bc
--- /dev/null
+++ b/assets/keycloak/data/import/genaistudio-realm.json
@@ -0,0 +1,1941 @@
+{
+ "id" : "f0f6258f-3d8e-4e5d-badd-8a7c0e653174",
+ "realm" : "genaistudio",
+ "displayName" : "GenAI Studio",
+ "displayNameHtml" : "GenAI Studio",
+ "notBefore" : 0,
+ "defaultSignatureAlgorithm" : "RS256",
+ "revokeRefreshToken" : false,
+ "refreshTokenMaxReuse" : 0,
+ "accessTokenLifespan" : 300,
+ "accessTokenLifespanForImplicitFlow" : 900,
+ "ssoSessionIdleTimeout" : 1800,
+ "ssoSessionMaxLifespan" : 36000,
+ "ssoSessionIdleTimeoutRememberMe" : 0,
+ "ssoSessionMaxLifespanRememberMe" : 0,
+ "offlineSessionIdleTimeout" : 2592000,
+ "offlineSessionMaxLifespanEnabled" : false,
+ "offlineSessionMaxLifespan" : 5184000,
+ "clientSessionIdleTimeout" : 0,
+ "clientSessionMaxLifespan" : 0,
+ "clientOfflineSessionIdleTimeout" : 0,
+ "clientOfflineSessionMaxLifespan" : 0,
+ "accessCodeLifespan" : 60,
+ "accessCodeLifespanUserAction" : 300,
+ "accessCodeLifespanLogin" : 1800,
+ "actionTokenGeneratedByAdminLifespan" : 43200,
+ "actionTokenGeneratedByUserLifespan" : 300,
+ "oauth2DeviceCodeLifespan" : 600,
+ "oauth2DevicePollingInterval" : 5,
+ "enabled" : true,
+ "sslRequired" : "external",
+ "registrationAllowed" : true,
+ "registrationEmailAsUsername" : false,
+ "rememberMe" : true,
+ "verifyEmail" : false,
+ "loginWithEmailAllowed" : true,
+ "duplicateEmailsAllowed" : false,
+ "resetPasswordAllowed" : true,
+ "editUsernameAllowed" : false,
+ "bruteForceProtected" : false,
+ "permanentLockout" : false,
+ "maxTemporaryLockouts" : 0,
+ "bruteForceStrategy" : "MULTIPLE",
+ "maxFailureWaitSeconds" : 900,
+ "minimumQuickLoginWaitSeconds" : 60,
+ "waitIncrementSeconds" : 60,
+ "quickLoginCheckMilliSeconds" : 1000,
+ "maxDeltaTimeSeconds" : 43200,
+ "failureFactor" : 30,
+ "roles" : {
+ "realm" : [ {
+ "id" : "7caf3bfc-c7c3-4b0e-b5ec-b9bc8a654e84",
+ "name" : "offline_access",
+ "description" : "${role_offline-access}",
+ "composite" : false,
+ "clientRole" : false,
+ "containerId" : "f0f6258f-3d8e-4e5d-badd-8a7c0e653174",
+ "attributes" : { }
+ }, {
+ "id" : "0bb42ee8-c34e-409c-adac-225aa09e291c",
+ "name" : "default-roles-genaistudio",
+ "description" : "${role_default-roles}",
+ "composite" : true,
+ "composites" : {
+ "realm" : [ "offline_access", "uma_authorization" ],
+ "client" : {
+ "account" : [ "view-profile", "manage-account" ]
+ }
+ },
+ "clientRole" : false,
+ "containerId" : "f0f6258f-3d8e-4e5d-badd-8a7c0e653174",
+ "attributes" : { }
+ }, {
+ "id" : "54bcc73e-26cf-4b63-8e90-70955aa31c54",
+ "name" : "uma_authorization",
+ "description" : "${role_uma_authorization}",
+ "composite" : false,
+ "clientRole" : false,
+ "containerId" : "f0f6258f-3d8e-4e5d-badd-8a7c0e653174",
+ "attributes" : { }
+ } ],
+ "client" : {
+ "genaistudio" : [ {
+ "id" : "c297e886-fd41-4872-9225-a2a7cc245006",
+ "name" : "user",
+ "description" : "",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "e633b3fa-4e80-4f6f-9729-bcc81730b065",
+ "attributes" : { }
+ }, {
+ "id" : "76be62ca-d269-47a9-87f2-d30a323c4e9c",
+ "name" : "admin",
+ "description" : "",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "e633b3fa-4e80-4f6f-9729-bcc81730b065",
+ "attributes" : { }
+ }, {
+ "id" : "b808e2c7-22d8-43a0-907c-97bd53fc5c62",
+ "name" : "unauthorized_user",
+ "description" : "",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "e633b3fa-4e80-4f6f-9729-bcc81730b065",
+ "attributes" : { }
+ } ],
+ "realm-management" : [ {
+ "id" : "5057426f-734c-4449-8bce-8bcabcb9c89e",
+ "name" : "query-users",
+ "description" : "${role_query-users}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "c83297ad-c816-4e71-a13b-e76aa6966fd8",
+ "name" : "manage-clients",
+ "description" : "${role_manage-clients}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "01646fa8-0b26-4643-8081-6678cda82ca0",
+ "name" : "impersonation",
+ "description" : "${role_impersonation}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "d438b592-4548-4438-9895-c5ca3b3cd7e0",
+ "name" : "manage-events",
+ "description" : "${role_manage-events}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "548a04e5-c6d2-48c0-ad37-4067dd8f838c",
+ "name" : "view-users",
+ "description" : "${role_view-users}",
+ "composite" : true,
+ "composites" : {
+ "client" : {
+ "realm-management" : [ "query-users", "query-groups" ]
+ }
+ },
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "5d780758-b78f-4b25-ae9b-c5ad18789a0e",
+ "name" : "query-clients",
+ "description" : "${role_query-clients}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "c83ff668-2c8a-4ad0-b58d-401e32e1de91",
+ "name" : "create-client",
+ "description" : "${role_create-client}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "a7c1c0d0-f6ac-4aa7-a0a6-5d92ffe44851",
+ "name" : "view-identity-providers",
+ "description" : "${role_view-identity-providers}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "d105c5d8-172c-49ff-a727-df58e25bf2b7",
+ "name" : "query-groups",
+ "description" : "${role_query-groups}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "adaa7c93-3f3c-4910-bdac-37510e5257c2",
+ "name" : "query-realms",
+ "description" : "${role_query-realms}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "c52b4bad-7b37-4240-a2d7-19d1d278612b",
+ "name" : "view-authorization",
+ "description" : "${role_view-authorization}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "09fad556-0209-41ac-984d-2924ff80bd7d",
+ "name" : "manage-authorization",
+ "description" : "${role_manage-authorization}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "9364420d-1dc7-4bcf-af45-df729c2c09d1",
+ "name" : "view-clients",
+ "description" : "${role_view-clients}",
+ "composite" : true,
+ "composites" : {
+ "client" : {
+ "realm-management" : [ "query-clients" ]
+ }
+ },
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "0e477d3c-7c27-45c6-88f7-89d8a3a653e3",
+ "name" : "view-realm",
+ "description" : "${role_view-realm}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "946cb9e9-9cd7-479d-9bd6-72164beb1376",
+ "name" : "manage-realm",
+ "description" : "${role_manage-realm}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "5fe1ef93-bcff-4a53-af72-3664ffba72a7",
+ "name" : "realm-admin",
+ "description" : "${role_realm-admin}",
+ "composite" : true,
+ "composites" : {
+ "client" : {
+ "realm-management" : [ "query-users", "manage-clients", "impersonation", "view-users", "manage-events", "query-clients", "create-client", "view-identity-providers", "query-groups", "query-realms", "view-authorization", "manage-authorization", "view-clients", "view-realm", "manage-realm", "manage-users", "manage-identity-providers", "view-events" ]
+ }
+ },
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "8a63f0ee-7b5c-48dd-aaa7-e5ccf036ab2a",
+ "name" : "manage-users",
+ "description" : "${role_manage-users}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "60a45e8b-a1fc-46ee-b843-ca2c418e6a59",
+ "name" : "manage-identity-providers",
+ "description" : "${role_manage-identity-providers}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ }, {
+ "id" : "952fb1d1-5672-4ac7-b0f7-e42ad3bc35db",
+ "name" : "view-events",
+ "description" : "${role_view-events}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "attributes" : { }
+ } ],
+ "security-admin-console" : [ ],
+ "admin-cli" : [ ],
+ "account-console" : [ ],
+ "broker" : [ {
+ "id" : "27b319ce-fbe7-4041-a2b2-b826402c04ae",
+ "name" : "read-token",
+ "description" : "${role_read-token}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "bc31d6e1-b2f8-4671-85c0-c9b9380d406f",
+ "attributes" : { }
+ } ],
+ "account" : [ {
+ "id" : "a5da1d90-cd1e-4a20-9218-f065e593bf5a",
+ "name" : "view-applications",
+ "description" : "${role_view-applications}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "42fc0ffe-9fb7-407e-bbc6-955089084958",
+ "attributes" : { }
+ }, {
+ "id" : "1a389fca-5265-48d4-93d7-1c12a5d982a6",
+ "name" : "view-profile",
+ "description" : "${role_view-profile}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "42fc0ffe-9fb7-407e-bbc6-955089084958",
+ "attributes" : { }
+ }, {
+ "id" : "be62e167-b3f7-4f0e-ac70-31d890275fec",
+ "name" : "manage-account-links",
+ "description" : "${role_manage-account-links}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "42fc0ffe-9fb7-407e-bbc6-955089084958",
+ "attributes" : { }
+ }, {
+ "id" : "4e872665-87d4-49be-82ae-14c78c0692cb",
+ "name" : "view-groups",
+ "description" : "${role_view-groups}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "42fc0ffe-9fb7-407e-bbc6-955089084958",
+ "attributes" : { }
+ }, {
+ "id" : "7da07fdc-da2f-461f-966a-1317d9a5edc9",
+ "name" : "manage-account",
+ "description" : "${role_manage-account}",
+ "composite" : true,
+ "composites" : {
+ "client" : {
+ "account" : [ "manage-account-links" ]
+ }
+ },
+ "clientRole" : true,
+ "containerId" : "42fc0ffe-9fb7-407e-bbc6-955089084958",
+ "attributes" : { }
+ }, {
+ "id" : "591c18fd-10e4-4145-b5be-e25d414cfe15",
+ "name" : "delete-account",
+ "description" : "${role_delete-account}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "42fc0ffe-9fb7-407e-bbc6-955089084958",
+ "attributes" : { }
+ }, {
+ "id" : "f862b279-0431-4fa5-9a4c-8aa131fbffe6",
+ "name" : "view-consent",
+ "description" : "${role_view-consent}",
+ "composite" : false,
+ "clientRole" : true,
+ "containerId" : "42fc0ffe-9fb7-407e-bbc6-955089084958",
+ "attributes" : { }
+ }, {
+ "id" : "b78bacd6-a1d5-4831-8317-aa7965c11a40",
+ "name" : "manage-consent",
+ "description" : "${role_manage-consent}",
+ "composite" : true,
+ "composites" : {
+ "client" : {
+ "account" : [ "view-consent" ]
+ }
+ },
+ "clientRole" : true,
+ "containerId" : "42fc0ffe-9fb7-407e-bbc6-955089084958",
+ "attributes" : { }
+ } ]
+ }
+ },
+ "groups" : [ {
+ "id" : "ae716f5a-1116-4944-bc46-2cbbc67b4683",
+ "name" : "admin",
+ "path" : "/admin",
+ "subGroups" : [ ],
+ "attributes" : { },
+ "realmRoles" : [ ],
+ "clientRoles" : {
+ "genaistudio" : [ "admin" ]
+ }
+ }, {
+ "id" : "3230ec0a-8338-4275-b890-bc7290e9b631",
+ "name" : "unauthorized_user",
+ "path" : "/unauthorized_user",
+ "subGroups" : [ ],
+ "attributes" : { },
+ "realmRoles" : [ ],
+ "clientRoles" : {
+ "genaistudio" : [ "unauthorized_user" ]
+ }
+ }, {
+ "id" : "b39c9159-f2d5-459d-af95-339529c27a8a",
+ "name" : "user",
+ "path" : "/user",
+ "subGroups" : [ ],
+ "attributes" : { },
+ "realmRoles" : [ ],
+ "clientRoles" : {
+ "genaistudio" : [ "user" ]
+ }
+ } ],
+ "defaultRole" : {
+ "id" : "0bb42ee8-c34e-409c-adac-225aa09e291c",
+ "name" : "default-roles-genaistudio",
+ "description" : "${role_default-roles}",
+ "composite" : true,
+ "clientRole" : false,
+ "containerId" : "f0f6258f-3d8e-4e5d-badd-8a7c0e653174"
+ },
+ "defaultGroups" : [ "/unauthorized_user" ],
+ "requiredCredentials" : [ "password" ],
+ "otpPolicyType" : "totp",
+ "otpPolicyAlgorithm" : "HmacSHA1",
+ "otpPolicyInitialCounter" : 0,
+ "otpPolicyDigits" : 6,
+ "otpPolicyLookAheadWindow" : 1,
+ "otpPolicyPeriod" : 30,
+ "otpPolicyCodeReusable" : false,
+ "otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ],
+ "localizationTexts" : { },
+ "webAuthnPolicyRpEntityName" : "keycloak",
+ "webAuthnPolicySignatureAlgorithms" : [ "ES256" ],
+ "webAuthnPolicyRpId" : "",
+ "webAuthnPolicyAttestationConveyancePreference" : "not specified",
+ "webAuthnPolicyAuthenticatorAttachment" : "not specified",
+ "webAuthnPolicyRequireResidentKey" : "not specified",
+ "webAuthnPolicyUserVerificationRequirement" : "not specified",
+ "webAuthnPolicyCreateTimeout" : 0,
+ "webAuthnPolicyAvoidSameAuthenticatorRegister" : false,
+ "webAuthnPolicyAcceptableAaguids" : [ ],
+ "webAuthnPolicyExtraOrigins" : [ ],
+ "webAuthnPolicyPasswordlessRpEntityName" : "keycloak",
+ "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ],
+ "webAuthnPolicyPasswordlessRpId" : "",
+ "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified",
+ "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified",
+ "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified",
+ "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified",
+ "webAuthnPolicyPasswordlessCreateTimeout" : 0,
+ "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false,
+ "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ],
+ "webAuthnPolicyPasswordlessExtraOrigins" : [ ],
+ "scopeMappings" : [ {
+ "clientScope" : "offline_access",
+ "roles" : [ "offline_access" ]
+ } ],
+ "clientScopeMappings" : {
+ "account" : [ {
+ "client" : "account-console",
+ "roles" : [ "manage-account", "view-groups" ]
+ } ]
+ },
+ "clients" : [ {
+ "id" : "42fc0ffe-9fb7-407e-bbc6-955089084958",
+ "clientId" : "account",
+ "name" : "${client_account}",
+ "rootUrl" : "${authBaseUrl}",
+ "baseUrl" : "/realms/genaistudio/account/",
+ "surrogateAuthRequired" : false,
+ "enabled" : true,
+ "alwaysDisplayInConsole" : false,
+ "clientAuthenticatorType" : "client-secret",
+ "redirectUris" : [ "/realms/genaistudio/account/*" ],
+ "webOrigins" : [ ],
+ "notBefore" : 0,
+ "bearerOnly" : false,
+ "consentRequired" : false,
+ "standardFlowEnabled" : true,
+ "implicitFlowEnabled" : false,
+ "directAccessGrantsEnabled" : false,
+ "serviceAccountsEnabled" : false,
+ "publicClient" : true,
+ "frontchannelLogout" : false,
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "realm_client" : "false",
+ "post.logout.redirect.uris" : "+"
+ },
+ "authenticationFlowBindingOverrides" : { },
+ "fullScopeAllowed" : false,
+ "nodeReRegistrationTimeout" : 0,
+ "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ],
+ "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ]
+ }, {
+ "id" : "afe0f5f0-4fe5-480d-a5b8-e454f3de8492",
+ "clientId" : "account-console",
+ "name" : "${client_account-console}",
+ "rootUrl" : "${authBaseUrl}",
+ "baseUrl" : "/realms/genaistudio/account/",
+ "surrogateAuthRequired" : false,
+ "enabled" : true,
+ "alwaysDisplayInConsole" : false,
+ "clientAuthenticatorType" : "client-secret",
+ "redirectUris" : [ "/realms/genaistudio/account/*" ],
+ "webOrigins" : [ ],
+ "notBefore" : 0,
+ "bearerOnly" : false,
+ "consentRequired" : false,
+ "standardFlowEnabled" : true,
+ "implicitFlowEnabled" : false,
+ "directAccessGrantsEnabled" : false,
+ "serviceAccountsEnabled" : false,
+ "publicClient" : true,
+ "frontchannelLogout" : false,
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "realm_client" : "false",
+ "post.logout.redirect.uris" : "+",
+ "pkce.code.challenge.method" : "S256"
+ },
+ "authenticationFlowBindingOverrides" : { },
+ "fullScopeAllowed" : false,
+ "nodeReRegistrationTimeout" : 0,
+ "protocolMappers" : [ {
+ "id" : "85ac6f06-a0fe-4bb7-af51-f534eb607ecf",
+ "name" : "audience resolve",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-audience-resolve-mapper",
+ "consentRequired" : false,
+ "config" : { }
+ } ],
+ "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ],
+ "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ]
+ }, {
+ "id" : "f278e305-b2c8-4571-9492-894ca8bfa79a",
+ "clientId" : "admin-cli",
+ "name" : "${client_admin-cli}",
+ "surrogateAuthRequired" : false,
+ "enabled" : true,
+ "alwaysDisplayInConsole" : false,
+ "clientAuthenticatorType" : "client-secret",
+ "redirectUris" : [ ],
+ "webOrigins" : [ ],
+ "notBefore" : 0,
+ "bearerOnly" : false,
+ "consentRequired" : false,
+ "standardFlowEnabled" : false,
+ "implicitFlowEnabled" : false,
+ "directAccessGrantsEnabled" : true,
+ "serviceAccountsEnabled" : false,
+ "publicClient" : true,
+ "frontchannelLogout" : false,
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "realm_client" : "false",
+ "client.use.lightweight.access.token.enabled" : "true",
+ "post.logout.redirect.uris" : "+"
+ },
+ "authenticationFlowBindingOverrides" : { },
+ "fullScopeAllowed" : true,
+ "nodeReRegistrationTimeout" : 0,
+ "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ],
+ "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ]
+ }, {
+ "id" : "bc31d6e1-b2f8-4671-85c0-c9b9380d406f",
+ "clientId" : "broker",
+ "name" : "${client_broker}",
+ "surrogateAuthRequired" : false,
+ "enabled" : true,
+ "alwaysDisplayInConsole" : false,
+ "clientAuthenticatorType" : "client-secret",
+ "redirectUris" : [ ],
+ "webOrigins" : [ ],
+ "notBefore" : 0,
+ "bearerOnly" : true,
+ "consentRequired" : false,
+ "standardFlowEnabled" : true,
+ "implicitFlowEnabled" : false,
+ "directAccessGrantsEnabled" : false,
+ "serviceAccountsEnabled" : false,
+ "publicClient" : false,
+ "frontchannelLogout" : false,
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "realm_client" : "true",
+ "post.logout.redirect.uris" : "+"
+ },
+ "authenticationFlowBindingOverrides" : { },
+ "fullScopeAllowed" : false,
+ "nodeReRegistrationTimeout" : 0,
+ "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ],
+ "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ]
+ }, {
+ "id" : "e633b3fa-4e80-4f6f-9729-bcc81730b065",
+ "clientId" : "genaistudio",
+ "name" : "GenAI Studio",
+ "description" : "",
+ "rootUrl" : "",
+ "adminUrl" : "",
+ "baseUrl" : "",
+ "surrogateAuthRequired" : false,
+ "enabled" : true,
+ "alwaysDisplayInConsole" : false,
+ "clientAuthenticatorType" : "client-secret",
+ "redirectUris" : [ "", "*" ],
+ "webOrigins" : [ "", "*" ],
+ "notBefore" : 0,
+ "bearerOnly" : false,
+ "consentRequired" : false,
+ "standardFlowEnabled" : true,
+ "implicitFlowEnabled" : false,
+ "directAccessGrantsEnabled" : true,
+ "serviceAccountsEnabled" : false,
+ "publicClient" : true,
+ "frontchannelLogout" : true,
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "realm_client" : "false",
+ "oidc.ciba.grant.enabled" : "false",
+ "backchannel.logout.session.required" : "true",
+ "login_theme" : "opea",
+ "post.logout.redirect.uris" : "+",
+ "oauth2.device.authorization.grant.enabled" : "false",
+ "display.on.consent.screen" : "false",
+ "backchannel.logout.revoke.offline.tokens" : "false"
+ },
+ "authenticationFlowBindingOverrides" : { },
+ "fullScopeAllowed" : true,
+ "nodeReRegistrationTimeout" : -1,
+ "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ],
+ "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ]
+ }, {
+ "id" : "ba4ab4d4-f111-47e2-bbb5-a34b85649481",
+ "clientId" : "realm-management",
+ "name" : "${client_realm-management}",
+ "surrogateAuthRequired" : false,
+ "enabled" : true,
+ "alwaysDisplayInConsole" : false,
+ "clientAuthenticatorType" : "client-secret",
+ "redirectUris" : [ ],
+ "webOrigins" : [ ],
+ "notBefore" : 0,
+ "bearerOnly" : true,
+ "consentRequired" : false,
+ "standardFlowEnabled" : true,
+ "implicitFlowEnabled" : false,
+ "directAccessGrantsEnabled" : false,
+ "serviceAccountsEnabled" : false,
+ "publicClient" : false,
+ "frontchannelLogout" : false,
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "realm_client" : "true",
+ "post.logout.redirect.uris" : "+"
+ },
+ "authenticationFlowBindingOverrides" : { },
+ "fullScopeAllowed" : false,
+ "nodeReRegistrationTimeout" : 0,
+ "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ],
+ "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ]
+ }, {
+ "id" : "1bac263b-bf38-46d0-877d-72f1f0867db7",
+ "clientId" : "security-admin-console",
+ "name" : "${client_security-admin-console}",
+ "rootUrl" : "${authAdminUrl}",
+ "baseUrl" : "/admin/genaistudio/console/",
+ "surrogateAuthRequired" : false,
+ "enabled" : true,
+ "alwaysDisplayInConsole" : false,
+ "clientAuthenticatorType" : "client-secret",
+ "redirectUris" : [ "/admin/genaistudio/console/*" ],
+ "webOrigins" : [ "+" ],
+ "notBefore" : 0,
+ "bearerOnly" : false,
+ "consentRequired" : false,
+ "standardFlowEnabled" : true,
+ "implicitFlowEnabled" : false,
+ "directAccessGrantsEnabled" : false,
+ "serviceAccountsEnabled" : false,
+ "publicClient" : true,
+ "frontchannelLogout" : false,
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "realm_client" : "false",
+ "client.use.lightweight.access.token.enabled" : "true",
+ "post.logout.redirect.uris" : "+",
+ "pkce.code.challenge.method" : "S256"
+ },
+ "authenticationFlowBindingOverrides" : { },
+ "fullScopeAllowed" : true,
+ "nodeReRegistrationTimeout" : 0,
+ "protocolMappers" : [ {
+ "id" : "ea29252d-4bf8-4dbb-9e73-70ae0b920be5",
+ "name" : "locale",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "locale",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "locale",
+ "jsonType.label" : "String"
+ }
+ } ],
+ "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ],
+ "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ]
+ } ],
+ "clientScopes" : [ {
+ "id" : "d28d60d4-33c5-4342-90e1-4371fe4a4d63",
+ "name" : "offline_access",
+ "description" : "OpenID Connect built-in scope: offline_access",
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "consent.screen.text" : "${offlineAccessScopeConsentText}",
+ "display.on.consent.screen" : "true"
+ }
+ }, {
+ "id" : "865b1897-98e2-4607-807a-f2fff6c6b267",
+ "name" : "email",
+ "description" : "OpenID Connect built-in scope: email",
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "include.in.token.scope" : "true",
+ "consent.screen.text" : "${emailScopeConsentText}",
+ "display.on.consent.screen" : "true"
+ },
+ "protocolMappers" : [ {
+ "id" : "898a0546-0826-4625-8741-872004030ad6",
+ "name" : "email",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "email",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "email",
+ "jsonType.label" : "String"
+ }
+ }, {
+ "id" : "81bda91e-8d1d-4152-957d-f7b5d236a3a9",
+ "name" : "email verified",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-property-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "emailVerified",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "email_verified",
+ "jsonType.label" : "boolean"
+ }
+ } ]
+ }, {
+ "id" : "e1aed2bc-91d7-40eb-a3fa-195463826bc7",
+ "name" : "microprofile-jwt",
+ "description" : "Microprofile - JWT built-in scope",
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "include.in.token.scope" : "true",
+ "display.on.consent.screen" : "false"
+ },
+ "protocolMappers" : [ {
+ "id" : "227f6fce-c7b2-45e5-accd-0a098b8cf12a",
+ "name" : "groups",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-realm-role-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "multivalued" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "foo",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "groups",
+ "jsonType.label" : "String"
+ }
+ }, {
+ "id" : "c09534ae-c78d-4339-aff4-2dbd5bbed6e7",
+ "name" : "upn",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "username",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "upn",
+ "jsonType.label" : "String"
+ }
+ } ]
+ }, {
+ "id" : "ec9c2a4b-b9e3-4e22-8390-bb1052251469",
+ "name" : "roles",
+ "description" : "OpenID Connect scope for add user roles to the access token",
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "include.in.token.scope" : "false",
+ "consent.screen.text" : "${rolesScopeConsentText}",
+ "display.on.consent.screen" : "true"
+ },
+ "protocolMappers" : [ {
+ "id" : "6df40c79-f290-4f94-85f5-c116b32f96f9",
+ "name" : "realm roles",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-realm-role-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "user.attribute" : "foo",
+ "introspection.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "realm_access.roles",
+ "jsonType.label" : "String",
+ "multivalued" : "true"
+ }
+ }, {
+ "id" : "a3f50ef6-9688-45fb-a6e6-b8d2e8120484",
+ "name" : "audience resolve",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-audience-resolve-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "access.token.claim" : "true"
+ }
+ }, {
+ "id" : "d1d085f2-1799-4a7c-94b5-5d4d31f10df1",
+ "name" : "client roles",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-client-role-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "user.attribute" : "foo",
+ "introspection.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "resource_access.${client_id}.roles",
+ "jsonType.label" : "String",
+ "multivalued" : "true"
+ }
+ } ]
+ }, {
+ "id" : "89d77d5b-49b5-413a-99df-031c800738b1",
+ "name" : "web-origins",
+ "description" : "OpenID Connect scope for add allowed web origins to the access token",
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "include.in.token.scope" : "false",
+ "consent.screen.text" : "",
+ "display.on.consent.screen" : "false"
+ },
+ "protocolMappers" : [ {
+ "id" : "64b38a11-7da2-4276-9eeb-3db7170d445c",
+ "name" : "allowed web origins",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-allowed-origins-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "access.token.claim" : "true"
+ }
+ } ]
+ }, {
+ "id" : "60a52fb4-3dc2-4da7-9497-7058ec74e237",
+ "name" : "phone",
+ "description" : "OpenID Connect built-in scope: phone",
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "include.in.token.scope" : "true",
+ "consent.screen.text" : "${phoneScopeConsentText}",
+ "display.on.consent.screen" : "true"
+ },
+ "protocolMappers" : [ {
+ "id" : "049fd210-e3be-49b5-b6a9-ca0318c4a5e1",
+ "name" : "phone number",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "phoneNumber",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "phone_number",
+ "jsonType.label" : "String"
+ }
+ }, {
+ "id" : "b4f4144f-45e4-4c50-9fb6-43ee7da41259",
+ "name" : "phone number verified",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "phoneNumberVerified",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "phone_number_verified",
+ "jsonType.label" : "boolean"
+ }
+ } ]
+ }, {
+ "id" : "4683d831-547f-4105-96d4-87b5411459ef",
+ "name" : "basic",
+ "description" : "OpenID Connect scope for add all basic claims to the token",
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "include.in.token.scope" : "false",
+ "display.on.consent.screen" : "false"
+ },
+ "protocolMappers" : [ {
+ "id" : "fae5fa55-e4f6-4395-8148-ec38cf188df0",
+ "name" : "auth_time",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usersessionmodel-note-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "user.session.note" : "AUTH_TIME",
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "auth_time",
+ "jsonType.label" : "long"
+ }
+ }, {
+ "id" : "9fe81269-9c24-441b-ac98-b9df588c6e45",
+ "name" : "sub",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-sub-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "access.token.claim" : "true"
+ }
+ } ]
+ }, {
+ "id" : "39bd4d60-c7f0-4055-b59a-88ac67b3dda9",
+ "name" : "address",
+ "description" : "OpenID Connect built-in scope: address",
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "include.in.token.scope" : "true",
+ "consent.screen.text" : "${addressScopeConsentText}",
+ "display.on.consent.screen" : "true"
+ },
+ "protocolMappers" : [ {
+ "id" : "5ed47a69-03a2-4d49-8b39-cd203557bec0",
+ "name" : "address",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-address-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "user.attribute.formatted" : "formatted",
+ "user.attribute.country" : "country",
+ "introspection.token.claim" : "true",
+ "user.attribute.postal_code" : "postal_code",
+ "userinfo.token.claim" : "true",
+ "user.attribute.street" : "street",
+ "id.token.claim" : "true",
+ "user.attribute.region" : "region",
+ "access.token.claim" : "true",
+ "user.attribute.locality" : "locality"
+ }
+ } ]
+ }, {
+ "id" : "522bb0a5-4405-42fa-b801-6582cbde8674",
+ "name" : "acr",
+ "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token",
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "include.in.token.scope" : "false",
+ "display.on.consent.screen" : "false"
+ },
+ "protocolMappers" : [ {
+ "id" : "feb2efa1-7a1e-490c-8581-d4627c0acd41",
+ "name" : "acr loa level",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-acr-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "id.token.claim" : "true",
+ "introspection.token.claim" : "true",
+ "access.token.claim" : "true",
+ "userinfo.token.claim" : "true"
+ }
+ } ]
+ }, {
+ "id" : "9592d39a-6f04-4944-9edc-e8c6777d59c1",
+ "name" : "role_list",
+ "description" : "SAML role list",
+ "protocol" : "saml",
+ "attributes" : {
+ "consent.screen.text" : "${samlRoleListScopeConsentText}",
+ "display.on.consent.screen" : "true"
+ },
+ "protocolMappers" : [ {
+ "id" : "7fe17268-14e4-4579-b266-3d15cb5d50d1",
+ "name" : "role list",
+ "protocol" : "saml",
+ "protocolMapper" : "saml-role-list-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "single" : "false",
+ "attribute.nameformat" : "Basic",
+ "attribute.name" : "Role"
+ }
+ } ]
+ }, {
+ "id" : "135bcdc0-d9c4-43cd-a7e6-c60886ad6160",
+ "name" : "profile",
+ "description" : "OpenID Connect built-in scope: profile",
+ "protocol" : "openid-connect",
+ "attributes" : {
+ "include.in.token.scope" : "true",
+ "consent.screen.text" : "${profileScopeConsentText}",
+ "display.on.consent.screen" : "true"
+ },
+ "protocolMappers" : [ {
+ "id" : "3d22f534-a1e1-4847-ba81-94e5eef2d177",
+ "name" : "full name",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-full-name-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "id.token.claim" : "true",
+ "introspection.token.claim" : "true",
+ "access.token.claim" : "true",
+ "userinfo.token.claim" : "true"
+ }
+ }, {
+ "id" : "167bbdb0-0b0f-47f7-a58d-fbcac353352e",
+ "name" : "nickname",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "nickname",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "nickname",
+ "jsonType.label" : "String"
+ }
+ }, {
+ "id" : "e76bc6b8-f064-4a34-8d48-27b99f1fc5a2",
+ "name" : "gender",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "gender",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "gender",
+ "jsonType.label" : "String"
+ }
+ }, {
+ "id" : "50a25e72-c48e-4339-8331-dece5d0a6f47",
+ "name" : "locale",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "locale",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "locale",
+ "jsonType.label" : "String"
+ }
+ }, {
+ "id" : "1c2171a4-8b2d-4da6-8c7c-d39cf2cfd7f3",
+ "name" : "website",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "website",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "website",
+ "jsonType.label" : "String"
+ }
+ }, {
+ "id" : "dda46b19-095d-47e7-9847-ebf6afc77fae",
+ "name" : "username",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "username",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "preferred_username",
+ "jsonType.label" : "String"
+ }
+ }, {
+ "id" : "f030218a-527c-4c7a-adff-e2b577275684",
+ "name" : "picture",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "picture",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "picture",
+ "jsonType.label" : "String"
+ }
+ }, {
+ "id" : "2a795a1f-7285-433f-ad04-d4cdc0fb0c05",
+ "name" : "birthdate",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "birthdate",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "birthdate",
+ "jsonType.label" : "String"
+ }
+ }, {
+ "id" : "9800bad3-8f13-4d0b-ae69-138684ed802d",
+ "name" : "family name",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "lastName",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "family_name",
+ "jsonType.label" : "String"
+ }
+ }, {
+ "id" : "3557073b-ec30-42cb-8c1a-a50f00491e6b",
+ "name" : "profile",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "profile",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "profile",
+ "jsonType.label" : "String"
+ }
+ }, {
+ "id" : "ed1d6f02-96d2-4b27-a9a3-c8e382ae3e85",
+ "name" : "given name",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "firstName",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "given_name",
+ "jsonType.label" : "String"
+ }
+ }, {
+ "id" : "8689c904-5d56-40aa-a55b-1780d54ed226",
+ "name" : "zoneinfo",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "zoneinfo",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "zoneinfo",
+ "jsonType.label" : "String"
+ }
+ }, {
+ "id" : "40f61f77-c590-4a5e-9425-482d2e24ab13",
+ "name" : "middle name",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "middleName",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "middle_name",
+ "jsonType.label" : "String"
+ }
+ }, {
+ "id" : "6e9a49f5-2e6b-431f-bcc9-7b561be80c7a",
+ "name" : "updated at",
+ "protocol" : "openid-connect",
+ "protocolMapper" : "oidc-usermodel-attribute-mapper",
+ "consentRequired" : false,
+ "config" : {
+ "introspection.token.claim" : "true",
+ "userinfo.token.claim" : "true",
+ "user.attribute" : "updatedAt",
+ "id.token.claim" : "true",
+ "access.token.claim" : "true",
+ "claim.name" : "updated_at",
+ "jsonType.label" : "long"
+ }
+ } ]
+ } ],
+ "defaultDefaultClientScopes" : [ "role_list", "profile", "email", "roles", "web-origins", "acr", "basic" ],
+ "defaultOptionalClientScopes" : [ "offline_access", "address", "phone", "microprofile-jwt" ],
+ "browserSecurityHeaders" : {
+ "contentSecurityPolicyReportOnly" : "",
+ "xContentTypeOptions" : "nosniff",
+ "referrerPolicy" : "no-referrer",
+ "xRobotsTag" : "none",
+ "xFrameOptions" : "SAMEORIGIN",
+ "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
+ "xXSSProtection" : "1; mode=block",
+ "strictTransportSecurity" : "max-age=31536000; includeSubDomains"
+ },
+ "smtpServer" : { },
+ "loginTheme" : "opea",
+ "accountTheme" : "",
+ "adminTheme" : "opea",
+ "emailTheme" : "",
+ "eventsEnabled" : false,
+ "eventsListeners" : [ "jboss-logging" ],
+ "enabledEventTypes" : [ ],
+ "adminEventsEnabled" : false,
+ "adminEventsDetailsEnabled" : false,
+ "identityProviders" : [ ],
+ "identityProviderMappers" : [ ],
+ "components" : {
+ "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ {
+ "id" : "4beef511-1333-480e-8ed0-537507457969",
+ "name" : "Trusted Hosts",
+ "providerId" : "trusted-hosts",
+ "subType" : "anonymous",
+ "subComponents" : { },
+ "config" : {
+ "host-sending-registration-request-must-match" : [ "true" ],
+ "client-uris-must-match" : [ "true" ]
+ }
+ }, {
+ "id" : "b0d629f5-511e-4175-93d5-b07ddef2b171",
+ "name" : "Full Scope Disabled",
+ "providerId" : "scope",
+ "subType" : "anonymous",
+ "subComponents" : { },
+ "config" : { }
+ }, {
+ "id" : "ef914206-6789-43d6-8041-740c3e4f208c",
+ "name" : "Consent Required",
+ "providerId" : "consent-required",
+ "subType" : "anonymous",
+ "subComponents" : { },
+ "config" : { }
+ }, {
+ "id" : "d6ad3846-1295-49d2-908c-195c63cdd550",
+ "name" : "Allowed Client Scopes",
+ "providerId" : "allowed-client-templates",
+ "subType" : "authenticated",
+ "subComponents" : { },
+ "config" : {
+ "allow-default-scopes" : [ "true" ]
+ }
+ }, {
+ "id" : "403ddaa6-3a78-4582-906f-d6da4ca44963",
+ "name" : "Allowed Protocol Mapper Types",
+ "providerId" : "allowed-protocol-mappers",
+ "subType" : "authenticated",
+ "subComponents" : { },
+ "config" : {
+ "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-property-mapper", "saml-user-attribute-mapper", "oidc-full-name-mapper", "oidc-address-mapper", "oidc-usermodel-attribute-mapper", "saml-role-list-mapper" ]
+ }
+ }, {
+ "id" : "ac406d17-51a7-47b2-b201-9edcb67668c6",
+ "name" : "Max Clients Limit",
+ "providerId" : "max-clients",
+ "subType" : "anonymous",
+ "subComponents" : { },
+ "config" : {
+ "max-clients" : [ "200" ]
+ }
+ }, {
+ "id" : "144680b9-9c1c-4667-b264-75e12de128fe",
+ "name" : "Allowed Protocol Mapper Types",
+ "providerId" : "allowed-protocol-mappers",
+ "subType" : "anonymous",
+ "subComponents" : { },
+ "config" : {
+ "allowed-protocol-mapper-types" : [ "oidc-usermodel-attribute-mapper", "oidc-full-name-mapper", "oidc-usermodel-property-mapper", "oidc-address-mapper", "saml-role-list-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper", "saml-user-property-mapper" ]
+ }
+ }, {
+ "id" : "b0cce162-c1ff-43c6-bc07-6c7d0bf5ac90",
+ "name" : "Allowed Client Scopes",
+ "providerId" : "allowed-client-templates",
+ "subType" : "anonymous",
+ "subComponents" : { },
+ "config" : {
+ "allow-default-scopes" : [ "true" ]
+ }
+ } ],
+ "org.keycloak.keys.KeyProvider" : [ {
+ "id" : "27822c88-0dea-4fed-ae00-9989103439e1",
+ "name" : "aes-generated",
+ "providerId" : "aes-generated",
+ "subComponents" : { },
+ "config" : {
+ "kid" : [ "68040a81-9c69-4b83-a8fd-a6bceec66bb2" ],
+ "secret" : [ "Tz_DHdQ2ydeeD_8UW4i72Q" ],
+ "priority" : [ "100" ]
+ }
+ }, {
+ "id" : "aad34e8e-bff1-4cb6-9812-41eaabacc3cf",
+ "name" : "rsa-enc-generated",
+ "providerId" : "rsa-enc-generated",
+ "subComponents" : { },
+ "config" : {
+ "privateKey" : [ "MIIEpAIBAAKCAQEAvc2DtuEdbs72kognmXqhZ6RD5KnRnWCsQYxDKLQNbvC6i3O1eBVhDMG8i/0VKZJVtF4mffsE1/kaY+vWTbUim9oLmRlUM3MzZ7ZD2SIaXhS0Pr3qH1ipjrlAlxaz6lx0ygqzW5+XgwR6eN2aqSBSWY803CoJEN/E5L8yNLap/lRLliTPsuUsgwOENswkMD7P3Oqa2lU0nJuy6S7Vu+rq6UwfGudJLMpyKntYvYTz+mfattgEaFMom9iPANCRxq629loTxIjFGho1eN7OHFNx8pPAPYj0Kvig90Q+odzx6xReHVHT5TqzTGpJHWzameUcr//GTbQVxkFyMQudG5lg1wIDAQABAoIBACRn15RL8KPQ8c2gbQwM0Am7ocQp6IlpwhCekUEs7Ai0Buv5qTybyS4zuPEW/aioJ2U9y99NNxwf7TZuRYBJNpazR5c5mwN1XM5PUQtEdc9G5F3GerJBhOBZ2zA/zAmvaz1XuRhhb6PTR5SIWQKIrxL7m3WBYJTKfw8rNzuSL+AWwMOCowCni9ZQ7Y50zzdxZaO9dd00DgrT75ANQcjs7jC0ovi+Sa9YmwozIBsx7WyHs9nazqsTPezZy2DI662P134iHDeL42R9Lz2lKhQeTYia0Ac792rO0QeX4dTR16WWxs33hQJe9L84MtGEKgJBmZnJ3y18hGoZMGJVqnvq0YUCgYEA/HTPG39cY7KYbaaf0B8urP/bvZJCIOb3slGpr00tJ4g3hQ6UGvW355wXUoAo1keGk1BhJZedc/5rHN/1+5cs15zRLZj1Qq0nouQPYl7Gatml+OHjlEsWNisAtFIqsvYr8+9Ckic+/HVE/1+/uGH9pxGfgR1E4tE+mdWLSGuFXYsCgYEAwHeQFJAvPTQmtGAAjMx9xS5aigPsmiw6L/DqpKROsHpD96tM0/wRlh4NoRRam0gATCTn3arC3ITALK58wUnrpdwFtb0dESrXOkqsQYHvMd21ytGxUMngCasPbWtUBvwG7IWkuixxyfWvLf0yDnIIwmXC80NcG9cc7E36Ulqzi2UCgYB90GTqykUr9nSaqOCaYv/q/bPwPPSx2wl0l9gd4jNvsSYiLIrJCM43IgZJek9fwtOhlPxlNLMmfJO7Fy5KzSNu7Nseg00vhoXrWwcDukHePEvHxiOZ4vXV1waJ1y0qdR6gegvONLriLDtPndM5O7Siz1iTixeqhidRmSfJ1rPnUwKBgQCsOJCJhfdvScI0dw8m7jjAf1ju1NIbpuWuTmJ4TrpG+jDlZrgJnC3UaTIC6Canekch24hK9ukE0BjyInRptQ6SzI2jcQSYfwA2HemDeJQjx+NLCFYlF29M12+nlnmLAmvjqzaajPiJIjnN6hmniWzDHrHSYX0DQHqWDLSoipbMbQKBgQCY3tKzhK6Felr+C5lX4VEdpyQ1CWuX4FHjUMy2XkMgYiOJq9ijU2EoY7W07zwpzSCi9HfzTmN75QuSC6cAfAsazGbmdIFUNyvk8a5r4VNjbb61hvDj/jzOUHe6Vk/z/JB5xrVJRKEfe01vVvz7XrHjeXIojEgDgs8bWSGSlQXz4w==" ],
+ "certificate" : [ "MIICpTCCAY0CBgGT2Sq1UjANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDDAtnZW5haXN0dWRpbzAeFw0yNDEyMTgwOTQ2MTVaFw0zNDEyMTgwOTQ3NTVaMBYxFDASBgNVBAMMC2dlbmFpc3R1ZGlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvc2DtuEdbs72kognmXqhZ6RD5KnRnWCsQYxDKLQNbvC6i3O1eBVhDMG8i/0VKZJVtF4mffsE1/kaY+vWTbUim9oLmRlUM3MzZ7ZD2SIaXhS0Pr3qH1ipjrlAlxaz6lx0ygqzW5+XgwR6eN2aqSBSWY803CoJEN/E5L8yNLap/lRLliTPsuUsgwOENswkMD7P3Oqa2lU0nJuy6S7Vu+rq6UwfGudJLMpyKntYvYTz+mfattgEaFMom9iPANCRxq629loTxIjFGho1eN7OHFNx8pPAPYj0Kvig90Q+odzx6xReHVHT5TqzTGpJHWzameUcr//GTbQVxkFyMQudG5lg1wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCIOcpv0Bv+meKej5WnKxB7BtX51cBqhkc6h7jtVWk4SYUkpyGGM+3TPAjzliCMDpYipxK6KC2Y6sTqDOmk4Vpqdy1174Z2YQwJUXxTlbSUgoNZbwwVcVue6daGCj2Qutp5mAPvT1vOtHewkubO5y0FJ+oxfCGM4IoVXfq9IfXiYNfjURKGOU0Kw9WudDbtuokGd0TiR0VYWxHValoLz+x7HeKoefaXnr4TfQuF1N8H3p2JNEyr91CSUvJKjLXKdaYrVu6y9FJuPTcyJ8W9DBQd24Lp/bA+xFeuWRmpOKCZftpPRlmgVD/rzEtORaMUpqs7gy98guX3qs0E57vaIv+N" ],
+ "priority" : [ "100" ],
+ "algorithm" : [ "RSA-OAEP" ]
+ }
+ }, {
+ "id" : "508351be-b48c-4935-939f-cc39019140c4",
+ "name" : "hmac-generated-hs512",
+ "providerId" : "hmac-generated",
+ "subComponents" : { },
+ "config" : {
+ "kid" : [ "ec96911a-9154-4ecf-b722-d10ba648a031" ],
+ "secret" : [ "yJGYiZibpOb881NZ-Ya3Zx7hqra9dNFSSOoxgoNZF8esWAsggJPFPyGxPwPkfGi0s1Nc6FRkNccMm6vhQKROhHIk22eEYBq8aNTFkjcbcGLhN65uuxQmONAyi7zvbwlJuAF5Kldj0IhAr4_lMexAPcaDbzqmJmtw-hyZ3t1XBHE" ],
+ "priority" : [ "100" ],
+ "algorithm" : [ "HS512" ]
+ }
+ }, {
+ "id" : "ee246737-ac46-4aa7-9b07-a747246676a2",
+ "name" : "rsa-generated",
+ "providerId" : "rsa-generated",
+ "subComponents" : { },
+ "config" : {
+ "privateKey" : [ "MIIEowIBAAKCAQEA5u/9sI5z8woL0UlDaGCEy57GCj4KFtJnMdOvWjag+1TwvoD1d/kXVOM4UnKpICSS+bp6rohnoeeX0EMVKULk2NLXkhwMGXWxAcu8bRqjuSLJVKoKM+tj5hIAuDLeENmAkF+8FybEE+AewGEzY7eGH/N1yAeEbo3DTj34HtPvrvFm5BdlvvbxWByQAfTmKpT98WcZI7PhOKBCwZAOUP2NHG1botgG+ausK0bgjWd1wXPH17NwaA2sX3BeLrFSNLy1ZgX3RMEA+rSGPY2BgSt5CDw+y/IHg8Hy9gyAlHfUBGayAUsw8w575pe7AC1ez/2hvMW4+bNkXwyR45BpOCWpwwIDAQABAoIBAACIgJjShARf5a25pb9/UdZA9orW5G7gZtpiCqBgjBKW7dtNFYtfTupnMs59twkjWltGVarxMheZndlv6mQ/VXF5jOve8BaM31NSHdb3yHyDicYRW9tPIhoDWbUy4v4FEtOMI8QS39chiT8VTH6yR0crV6YJsU7lYkvtF8zsDMIOy3S+QN98be8ns0OzsM5HPlkp2K/pgXRNNntCzKqFBgKRtFurVFxF7Nht62ubbvu2uEFGOnUWj7ldk/MLGIJOZJ3oeGJVP0EDM1j+59UkTW3tbA/qwxavJFzS/qfgMwMLItmWz4PngR3kvfQoOrxh0WMRSWaye4O6X9aKryvyRdECgYEA9k/loc707WfYN/0C021qEATEa+dP+xPGiBuUEyqbaZCFTfgz+OPk80QEA7Gl3L/kduhO0DjZoccuHJy2sojzT2npsfpRY1L252pRsq0DOwj07pIH2B8TQTa/E5SeoAmrd2Vpt20j57R5uiss6yLjnRgZUkDoxUExPauOxOA9XZkCgYEA8AVJosCD5uhlf/jR1XAOIHvS+TD0fSyo8bTABfk65oH0QjLP9iTVZ0rBhcKzjvr+5IzuLMWIGG6uQLLmb4u/mjSZzrvfB6ZAyp1L7GRzLpd6FbZTtewOEwuP8PQw9lHa+/+NYdOC1a6qZWrbfPyqz2sTXJz9y7C8m5DZB5n1g7sCgYBkwhBEnb1xtE4tsRFL3fFKNjkHjusX4WIQYX+0S3ShvV3apFLWWJtarBMcU7pu0AysW6GJ6geU9z60s6LE6+LkNIZFqQlMIS8hQUvEVKQCrUpMoW4WCbg9sCB/6QbunqYGxHR3dWz/psM41dqdIXuM0sPg8u6FaoKzII/Zl4Vi2QKBgQCSqrh/YmJ3hEUZuQMICMwpH2Eg8sBDiTnHUSsRu2U5m+mVVhVsFL/uuWieAwbT9R4yrMeRxjbOrzt9v5Q+T0gKw9/Ey1qTAw2OgiX10r/rlZZ9lAd9IDzNeIBBvgX5TrWgzV0ojSXiyzPGe1CaBI+f5Y9URX50rI/kA9QK6BJ1pwKBgDhHIuBFpfZcdgHJyhN1Txp6975CvTpzdvjyZ7xaXYcie4LZz4gLzOzqxLGtZ45WRWsphHJOlCvRo8OEe07oaCK13D3IAv0VKE5N6sdx18KUyKit7rzH6NJf5syUs0fnJhO0j2IU+DTHtEz33sPkqauhA77j8w+24d/IlT26Ii7J" ],
+ "certificate" : [ "MIICpTCCAY0CBgGT2Sq2EzANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDDAtnZW5haXN0dWRpbzAeFw0yNDEyMTgwOTQ2MTVaFw0zNDEyMTgwOTQ3NTVaMBYxFDASBgNVBAMMC2dlbmFpc3R1ZGlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5u/9sI5z8woL0UlDaGCEy57GCj4KFtJnMdOvWjag+1TwvoD1d/kXVOM4UnKpICSS+bp6rohnoeeX0EMVKULk2NLXkhwMGXWxAcu8bRqjuSLJVKoKM+tj5hIAuDLeENmAkF+8FybEE+AewGEzY7eGH/N1yAeEbo3DTj34HtPvrvFm5BdlvvbxWByQAfTmKpT98WcZI7PhOKBCwZAOUP2NHG1botgG+ausK0bgjWd1wXPH17NwaA2sX3BeLrFSNLy1ZgX3RMEA+rSGPY2BgSt5CDw+y/IHg8Hy9gyAlHfUBGayAUsw8w575pe7AC1ez/2hvMW4+bNkXwyR45BpOCWpwwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCHDmnQS0rQg4aTA4a0X1jyTH21UJ7LZ9JPSchHJ+cK52umqO4uSGRn+bakTb30Y0Pfr82UQfy+Pqkr9hJejGuKhEGI4UhgUW9BcI4qnvhQ3OW+S0/ffNE3Zq4sv2wmmBwDhBrSmvHL2bOKlCfbLeyzmab7qffuKqWxfkfbP7jsL4+LfFuG12Q79NFRvau7FPeFzwXFeXGOaWFqM7TNtS04WdymBnUVMBSHu1CQEoYHE055eEAIL7j7ONZ3Be3/Rb3PN1h/4oaW7SoYThHpHlsMJsCgONSN6PvI/QdiJRbdPJe6whFauReDrmbKwb+nD6pb6sz6G1Uf2ZGzmSJP3Fk8" ],
+ "priority" : [ "100" ]
+ }
+ } ]
+ },
+ "internationalizationEnabled" : false,
+ "supportedLocales" : [ ],
+ "authenticationFlows" : [ {
+ "id" : "d47dbbfd-6d2e-42d3-b45c-33c5eee77014",
+ "alias" : "Account verification options",
+ "description" : "Method with which to verity the existing account",
+ "providerId" : "basic-flow",
+ "topLevel" : false,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticator" : "idp-email-verification",
+ "authenticatorFlow" : false,
+ "requirement" : "ALTERNATIVE",
+ "priority" : 10,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticatorFlow" : true,
+ "requirement" : "ALTERNATIVE",
+ "priority" : 20,
+ "autheticatorFlow" : true,
+ "flowAlias" : "Verify Existing Account by Re-authentication",
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "8f92cd72-09c8-44aa-8434-65d5b94dd0e5",
+ "alias" : "Browser - Conditional OTP",
+ "description" : "Flow to determine if the OTP is required for the authentication",
+ "providerId" : "basic-flow",
+ "topLevel" : false,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticator" : "conditional-user-configured",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 10,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticator" : "auth-otp-form",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 20,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "fca7a70f-3060-4715-800f-e59134d71ed3",
+ "alias" : "Direct Grant - Conditional OTP",
+ "description" : "Flow to determine if the OTP is required for the authentication",
+ "providerId" : "basic-flow",
+ "topLevel" : false,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticator" : "conditional-user-configured",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 10,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticator" : "direct-grant-validate-otp",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 20,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "5228bb58-dbde-42cf-84b8-5099e9669fe3",
+ "alias" : "First broker login - Conditional OTP",
+ "description" : "Flow to determine if the OTP is required for the authentication",
+ "providerId" : "basic-flow",
+ "topLevel" : false,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticator" : "conditional-user-configured",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 10,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticator" : "auth-otp-form",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 20,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "01a8795e-e280-45cb-8bdf-d0a8d798c53c",
+ "alias" : "Handle Existing Account",
+ "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider",
+ "providerId" : "basic-flow",
+ "topLevel" : false,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticator" : "idp-confirm-link",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 10,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticatorFlow" : true,
+ "requirement" : "REQUIRED",
+ "priority" : 20,
+ "autheticatorFlow" : true,
+ "flowAlias" : "Account verification options",
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "3b45908f-85f7-4131-8b3c-f05b64252469",
+ "alias" : "Reset - Conditional OTP",
+ "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
+ "providerId" : "basic-flow",
+ "topLevel" : false,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticator" : "conditional-user-configured",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 10,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticator" : "reset-otp",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 20,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "109867e3-073b-4211-9a59-41ce1d42821c",
+ "alias" : "User creation or linking",
+ "description" : "Flow for the existing/non-existing user alternatives",
+ "providerId" : "basic-flow",
+ "topLevel" : false,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticatorConfig" : "create unique user config",
+ "authenticator" : "idp-create-user-if-unique",
+ "authenticatorFlow" : false,
+ "requirement" : "ALTERNATIVE",
+ "priority" : 10,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticatorFlow" : true,
+ "requirement" : "ALTERNATIVE",
+ "priority" : 20,
+ "autheticatorFlow" : true,
+ "flowAlias" : "Handle Existing Account",
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "0c9e8544-d902-47c8-8546-55efb3b84355",
+ "alias" : "Verify Existing Account by Re-authentication",
+ "description" : "Reauthentication of existing account",
+ "providerId" : "basic-flow",
+ "topLevel" : false,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticator" : "idp-username-password-form",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 10,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticatorFlow" : true,
+ "requirement" : "CONDITIONAL",
+ "priority" : 20,
+ "autheticatorFlow" : true,
+ "flowAlias" : "First broker login - Conditional OTP",
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "2b822d34-fd81-419c-b5a6-0f4dc98fed0e",
+ "alias" : "browser",
+ "description" : "browser based authentication",
+ "providerId" : "basic-flow",
+ "topLevel" : true,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticator" : "auth-cookie",
+ "authenticatorFlow" : false,
+ "requirement" : "ALTERNATIVE",
+ "priority" : 10,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticator" : "auth-spnego",
+ "authenticatorFlow" : false,
+ "requirement" : "DISABLED",
+ "priority" : 20,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticator" : "identity-provider-redirector",
+ "authenticatorFlow" : false,
+ "requirement" : "ALTERNATIVE",
+ "priority" : 25,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticatorFlow" : true,
+ "requirement" : "ALTERNATIVE",
+ "priority" : 30,
+ "autheticatorFlow" : true,
+ "flowAlias" : "forms",
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "f5947c13-adf9-4606-8b18-e978265bf037",
+ "alias" : "clients",
+ "description" : "Base authentication for clients",
+ "providerId" : "client-flow",
+ "topLevel" : true,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticator" : "client-secret",
+ "authenticatorFlow" : false,
+ "requirement" : "ALTERNATIVE",
+ "priority" : 10,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticator" : "client-jwt",
+ "authenticatorFlow" : false,
+ "requirement" : "ALTERNATIVE",
+ "priority" : 20,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticator" : "client-secret-jwt",
+ "authenticatorFlow" : false,
+ "requirement" : "ALTERNATIVE",
+ "priority" : 30,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticator" : "client-x509",
+ "authenticatorFlow" : false,
+ "requirement" : "ALTERNATIVE",
+ "priority" : 40,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "59496ed1-e246-4541-8f61-59e34d50c162",
+ "alias" : "direct grant",
+ "description" : "OpenID Connect Resource Owner Grant",
+ "providerId" : "basic-flow",
+ "topLevel" : true,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticator" : "direct-grant-validate-username",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 10,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticator" : "direct-grant-validate-password",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 20,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticatorFlow" : true,
+ "requirement" : "CONDITIONAL",
+ "priority" : 30,
+ "autheticatorFlow" : true,
+ "flowAlias" : "Direct Grant - Conditional OTP",
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "07c4e744-67e1-486e-bf3f-e25685719f03",
+ "alias" : "docker auth",
+ "description" : "Used by Docker clients to authenticate against the IDP",
+ "providerId" : "basic-flow",
+ "topLevel" : true,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticator" : "docker-http-basic-authenticator",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 10,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "d3110098-3156-415b-9bef-6491a1f6315f",
+ "alias" : "first broker login",
+ "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
+ "providerId" : "basic-flow",
+ "topLevel" : true,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticatorConfig" : "review profile config",
+ "authenticator" : "idp-review-profile",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 10,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticatorFlow" : true,
+ "requirement" : "REQUIRED",
+ "priority" : 20,
+ "autheticatorFlow" : true,
+ "flowAlias" : "User creation or linking",
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "650db54f-26dd-4721-ae84-d4fa1fe5000d",
+ "alias" : "forms",
+ "description" : "Username, password, otp and other auth forms.",
+ "providerId" : "basic-flow",
+ "topLevel" : false,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticator" : "auth-username-password-form",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 10,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticatorFlow" : true,
+ "requirement" : "CONDITIONAL",
+ "priority" : 20,
+ "autheticatorFlow" : true,
+ "flowAlias" : "Browser - Conditional OTP",
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "73baa0b6-c435-47c2-b520-e039814ddf44",
+ "alias" : "registration",
+ "description" : "registration flow",
+ "providerId" : "basic-flow",
+ "topLevel" : true,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticator" : "registration-page-form",
+ "authenticatorFlow" : true,
+ "requirement" : "REQUIRED",
+ "priority" : 10,
+ "autheticatorFlow" : true,
+ "flowAlias" : "registration form",
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "92063908-3a5b-44ee-bd68-96c6e8e75476",
+ "alias" : "registration form",
+ "description" : "registration form",
+ "providerId" : "form-flow",
+ "topLevel" : false,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticator" : "registration-user-creation",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 20,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticator" : "registration-password-action",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 50,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticator" : "registration-recaptcha-action",
+ "authenticatorFlow" : false,
+ "requirement" : "DISABLED",
+ "priority" : 60,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticator" : "registration-terms-and-conditions",
+ "authenticatorFlow" : false,
+ "requirement" : "DISABLED",
+ "priority" : 70,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "296e20d1-9389-4378-b960-432e97313cb8",
+ "alias" : "reset credentials",
+ "description" : "Reset credentials for a user if they forgot their password or something",
+ "providerId" : "basic-flow",
+ "topLevel" : true,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticator" : "reset-credentials-choose-user",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 10,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticator" : "reset-credential-email",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 20,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticator" : "reset-password",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 30,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ }, {
+ "authenticatorFlow" : true,
+ "requirement" : "CONDITIONAL",
+ "priority" : 40,
+ "autheticatorFlow" : true,
+ "flowAlias" : "Reset - Conditional OTP",
+ "userSetupAllowed" : false
+ } ]
+ }, {
+ "id" : "ce6d811a-74be-44d1-b25d-97228fd58d0c",
+ "alias" : "saml ecp",
+ "description" : "SAML ECP Profile Authentication Flow",
+ "providerId" : "basic-flow",
+ "topLevel" : true,
+ "builtIn" : true,
+ "authenticationExecutions" : [ {
+ "authenticator" : "http-basic-authenticator",
+ "authenticatorFlow" : false,
+ "requirement" : "REQUIRED",
+ "priority" : 10,
+ "autheticatorFlow" : false,
+ "userSetupAllowed" : false
+ } ]
+ } ],
+ "authenticatorConfig" : [ {
+ "id" : "f2ce9b19-6b39-4804-b9d2-ddbf8950e968",
+ "alias" : "create unique user config",
+ "config" : {
+ "require.password.update.after.registration" : "false"
+ }
+ }, {
+ "id" : "ba967870-3e45-4306-a2c7-cef80cb0c53b",
+ "alias" : "review profile config",
+ "config" : {
+ "update.profile.on.first.login" : "missing"
+ }
+ } ],
+ "requiredActions" : [ {
+ "alias" : "CONFIGURE_TOTP",
+ "name" : "Configure OTP",
+ "providerId" : "CONFIGURE_TOTP",
+ "enabled" : true,
+ "defaultAction" : false,
+ "priority" : 10,
+ "config" : { }
+ }, {
+ "alias" : "TERMS_AND_CONDITIONS",
+ "name" : "Terms and Conditions",
+ "providerId" : "TERMS_AND_CONDITIONS",
+ "enabled" : false,
+ "defaultAction" : false,
+ "priority" : 20,
+ "config" : { }
+ }, {
+ "alias" : "UPDATE_PASSWORD",
+ "name" : "Update Password",
+ "providerId" : "UPDATE_PASSWORD",
+ "enabled" : true,
+ "defaultAction" : false,
+ "priority" : 30,
+ "config" : { }
+ }, {
+ "alias" : "UPDATE_PROFILE",
+ "name" : "Update Profile",
+ "providerId" : "UPDATE_PROFILE",
+ "enabled" : true,
+ "defaultAction" : false,
+ "priority" : 40,
+ "config" : { }
+ }, {
+ "alias" : "VERIFY_EMAIL",
+ "name" : "Verify Email",
+ "providerId" : "VERIFY_EMAIL",
+ "enabled" : true,
+ "defaultAction" : false,
+ "priority" : 50,
+ "config" : { }
+ }, {
+ "alias" : "delete_account",
+ "name" : "Delete Account",
+ "providerId" : "delete_account",
+ "enabled" : false,
+ "defaultAction" : false,
+ "priority" : 60,
+ "config" : { }
+ }, {
+ "alias" : "webauthn-register",
+ "name" : "Webauthn Register",
+ "providerId" : "webauthn-register",
+ "enabled" : true,
+ "defaultAction" : false,
+ "priority" : 70,
+ "config" : { }
+ }, {
+ "alias" : "webauthn-register-passwordless",
+ "name" : "Webauthn Register Passwordless",
+ "providerId" : "webauthn-register-passwordless",
+ "enabled" : true,
+ "defaultAction" : false,
+ "priority" : 80,
+ "config" : { }
+ }, {
+ "alias" : "VERIFY_PROFILE",
+ "name" : "Verify Profile",
+ "providerId" : "VERIFY_PROFILE",
+ "enabled" : true,
+ "defaultAction" : false,
+ "priority" : 90,
+ "config" : { }
+ }, {
+ "alias" : "delete_credential",
+ "name" : "Delete Credential",
+ "providerId" : "delete_credential",
+ "enabled" : true,
+ "defaultAction" : false,
+ "priority" : 100,
+ "config" : { }
+ }, {
+ "alias" : "update_user_locale",
+ "name" : "Update User Locale",
+ "providerId" : "update_user_locale",
+ "enabled" : true,
+ "defaultAction" : false,
+ "priority" : 1000,
+ "config" : { }
+ } ],
+ "browserFlow" : "browser",
+ "registrationFlow" : "registration",
+ "directGrantFlow" : "direct grant",
+ "resetCredentialsFlow" : "reset credentials",
+ "clientAuthenticationFlow" : "clients",
+ "dockerAuthenticationFlow" : "docker auth",
+ "firstBrokerLoginFlow" : "first broker login",
+ "attributes" : {
+ "cibaBackchannelTokenDeliveryMode" : "poll",
+ "cibaAuthRequestedUserHint" : "login_hint",
+ "clientOfflineSessionMaxLifespan" : "0",
+ "oauth2DevicePollingInterval" : "5",
+ "clientSessionIdleTimeout" : "0",
+ "clientOfflineSessionIdleTimeout" : "0",
+ "cibaInterval" : "5",
+ "realmReusableOtpCode" : "false",
+ "cibaExpiresIn" : "120",
+ "oauth2DeviceCodeLifespan" : "600",
+ "parRequestUriLifespan" : "60",
+ "clientSessionMaxLifespan" : "0",
+ "frontendUrl" : "",
+ "organizationsEnabled" : "false",
+ "acr.loa.map" : "{}"
+ },
+ "keycloakVersion" : "26.0.7",
+ "userManagedAccessAllowed" : false,
+ "organizationsEnabled" : false,
+ "clientProfiles" : {
+ "profiles" : [ ]
+ },
+ "clientPolicies" : {
+ "policies" : [ ]
+ }
+}
\ No newline at end of file
diff --git a/assets/keycloak/data/import/genaistudio-users-0.json b/assets/keycloak/data/import/genaistudio-users-0.json
new file mode 100644
index 0000000..00ff2fa
--- /dev/null
+++ b/assets/keycloak/data/import/genaistudio-users-0.json
@@ -0,0 +1,26 @@
+{
+ "realm" : "genaistudio",
+ "users" : [ {
+ "id" : "1133d20f-3c10-4bb3-b51a-1d68e426acf4",
+ "username" : "test_automation@gmail.com",
+ "firstName" : "test",
+ "lastName" : "test",
+ "email" : "test_automation@gmail.com",
+ "emailVerified" : false,
+ "createdTimestamp" : 1734518970757,
+ "enabled" : true,
+ "totp" : false,
+ "credentials" : [ {
+ "id" : "4e9468e9-27f5-41a2-9c8a-f759446e3ad5",
+ "type" : "password",
+ "createdDate" : 1734518970820,
+ "secretData" : "{\"value\":\"gm5NNTNC5AykgayjuY9Ci9nXLrY1x8BgL3EUjD7R1zs=\",\"salt\":\"lP/L902ch8edynC5EU4Q0Q==\",\"additionalParameters\":{}}",
+ "credentialData" : "{\"hashIterations\":5,\"algorithm\":\"argon2\",\"additionalParameters\":{\"hashLength\":[\"32\"],\"memory\":[\"7168\"],\"type\":[\"id\"],\"version\":[\"1.3\"],\"parallelism\":[\"1\"]}}"
+ } ],
+ "disableableCredentialTypes" : [ ],
+ "requiredActions" : [ ],
+ "realmRoles" : [ "default-roles-genaistudio" ],
+ "notBefore" : 0,
+ "groups" : [ "/user" ]
+ } ]
+}
\ No newline at end of file
diff --git a/assets/keycloak/themes/opea/admin/resources/css/styles.css b/assets/keycloak/themes/opea/admin/resources/css/styles.css
new file mode 100644
index 0000000..6795108
--- /dev/null
+++ b/assets/keycloak/themes/opea/admin/resources/css/styles.css
@@ -0,0 +1,9 @@
+/* admin/resources/css/styles.css file */
+/* Override global colors */
+:root {
+ --pf-global--primary-color--100: var(--pf-global--palette--purple-600);
+ --pf-global--primary-color--200: var(--pf-global--palette--purple-700);
+ --pf-global--active-color--100: var(--pf-global--palette--purple-600);
+ --pf-global--BackgroundColor--dark-300: #606C38;
+ --pf-global--BackgroundColor--dark-100: #283618;
+ }
\ No newline at end of file
diff --git a/assets/keycloak/themes/opea/admin/resources/favicon.svg b/assets/keycloak/themes/opea/admin/resources/favicon.svg
new file mode 100644
index 0000000..3c4b988
--- /dev/null
+++ b/assets/keycloak/themes/opea/admin/resources/favicon.svg
@@ -0,0 +1,19 @@
+
+
\ No newline at end of file
diff --git a/assets/keycloak/themes/opea/admin/resources/icon.svg b/assets/keycloak/themes/opea/admin/resources/icon.svg
new file mode 100644
index 0000000..3c4b988
--- /dev/null
+++ b/assets/keycloak/themes/opea/admin/resources/icon.svg
@@ -0,0 +1,19 @@
+
+
\ No newline at end of file
diff --git a/assets/keycloak/themes/opea/admin/resources/logo.svg b/assets/keycloak/themes/opea/admin/resources/logo.svg
new file mode 100644
index 0000000..da5c8a0
--- /dev/null
+++ b/assets/keycloak/themes/opea/admin/resources/logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/keycloak/themes/opea/admin/theme.properties b/assets/keycloak/themes/opea/admin/theme.properties
new file mode 100644
index 0000000..a781934
--- /dev/null
+++ b/assets/keycloak/themes/opea/admin/theme.properties
@@ -0,0 +1,5 @@
+# admin/theme.properties file
+
+parent=keycloak.v2
+import=common/keycloak
+styles=css/styles.css
\ No newline at end of file
diff --git a/assets/keycloak/themes/opea/login/resources/css/styles.css b/assets/keycloak/themes/opea/login/resources/css/styles.css
new file mode 100644
index 0000000..16366e7
--- /dev/null
+++ b/assets/keycloak/themes/opea/login/resources/css/styles.css
@@ -0,0 +1,635 @@
+/* Patternfly CSS places a "bg-login.jpg" as the background on this ".login-pf" class.
+ This clashes with the "keycloak-bg.png' background defined on the body below.
+ Therefore the Patternfly background must be set to none. */
+ .login-pf {
+ background: none;
+}
+
+.login-pf body {
+ background: url("../img/OPEA_Studio_bg.jpg") no-repeat center center fixed;
+ background-size:cover;
+ /* height: 100%; */
+}
+
+.login-pf-page .login-pf-page-header{
+ margin-bottom: 10px;
+}
+
+textarea.pf-c-form-control {
+ height: auto;
+}
+
+.pf-c-alert__title {
+ font-size: var(--pf-global--FontSize--xs);
+}
+
+p.instruction {
+ margin: 5px 0;
+}
+
+.pf-c-button.pf-m-control {
+ border-color: rgba(230, 230, 230, 0.5);
+}
+
+h1#kc-page-title {
+ margin-top: 10px;
+}
+
+#kc-locale ul {
+ background-color: var(--pf-global--BackgroundColor--100);
+ display: none;
+ top: 20px;
+ min-width: 100px;
+ padding: 0;
+}
+
+#kc-locale-dropdown{
+ display: inline-block;
+}
+
+#kc-locale-dropdown:hover ul {
+ display:block;
+}
+
+#kc-locale-dropdown a {
+ color: var(--pf-global--Color--200);
+ text-align: right;
+ font-size: var(--pf-global--FontSize--sm);
+}
+
+#kc-locale-dropdown button {
+ background: none;
+ border: none;
+ padding: 0;
+ cursor: pointer;
+ color: var(--pf-global--Color--200);
+ text-align: right;
+ font-size: var(--pf-global--FontSize--sm);
+}
+
+button#kc-current-locale-link::after {
+ content: "\2c5";
+ margin-left: var(--pf-global--spacer--xs)
+}
+
+.login-pf .container {
+ padding-top: 40px;
+}
+
+.login-pf a:hover {
+ color: #0099d3;
+}
+
+#kc-logo {
+ width: 100%;
+}
+
+div.kc-logo-text {
+ background-image: url(../img/keycloak-logo-text.png);
+ background-repeat: no-repeat;
+ /* height: 63px;
+ width: 300px; */
+ margin: 0 auto;
+}
+
+div.kc-logo-text span {
+ display: none;
+}
+
+#kc-header {
+ color: #ededed;
+ overflow: visible;
+ white-space: nowrap;
+}
+
+#kc-header-wrapper {
+ font-size: 29px;
+ color: darkorange;
+ text-transform: capitalize;
+ letter-spacing: 3px;
+ line-height: 1.2em;
+ padding: 200px 0px 0px;
+ white-space: normal;
+ font-weight: bold;
+}
+
+#kc-content {
+ width: 100%;
+}
+
+#kc-attempted-username {
+ font-size: 20px;
+ font-family: inherit;
+ font-weight: normal;
+ padding-right: 10px;
+}
+
+#kc-username {
+ text-align: center;
+ margin-bottom:-10px;
+}
+
+#kc-webauthn-settings-form {
+ padding-top: 8px;
+}
+
+#kc-form-webauthn .select-auth-box-parent {
+ pointer-events: none;
+}
+
+#kc-form-webauthn .select-auth-box-desc {
+ color: var(--pf-global--palette--black-600);
+}
+
+#kc-form-webauthn .select-auth-box-headline {
+ color: var(--pf-global--Color--300);
+}
+
+#kc-form-webauthn .select-auth-box-icon {
+ flex: 0 0 3em;
+}
+
+#kc-form-webauthn .select-auth-box-icon-properties {
+ margin-top: 10px;
+ font-size: 1.8em;
+}
+
+#kc-form-webauthn .select-auth-box-icon-properties.unknown-transport-class {
+ margin-top: 3px;
+}
+
+#kc-form-webauthn .pf-l-stack__item {
+ margin: -1px 0;
+}
+
+#kc-content-wrapper {
+ margin-top: 20px;
+}
+
+#kc-form-wrapper {
+ margin-top: 10px;
+}
+
+#kc-info {
+ margin: 20px -40px -30px;
+}
+
+#kc-info-wrapper {
+ font-size: 13px;
+ padding: 15px 35px;
+ background-color: #F0F0F0;
+}
+
+#kc-form-options span {
+ display: block;
+}
+
+#kc-form-options .checkbox {
+ margin-top: 0;
+ color: #72767b;
+}
+
+#kc-terms-text {
+ margin-bottom: 20px;
+}
+
+#kc-registration-terms-text {
+ max-height: 100px;
+ overflow-y: auto;
+ overflow-x: hidden;
+ margin: 5px;
+}
+
+#kc-registration {
+ margin-bottom: 0;
+}
+
+/* TOTP */
+
+.subtitle {
+ text-align: right;
+ margin-top: 30px;
+ color: #909090;
+}
+
+.required {
+ color: var(--pf-global--danger-color--200);
+}
+
+ol#kc-totp-settings {
+ margin: 0;
+ padding-left: 20px;
+}
+
+ul#kc-totp-supported-apps {
+ margin-bottom: 10px;
+}
+
+#kc-totp-secret-qr-code {
+ max-width:150px;
+ max-height:150px;
+}
+
+#kc-totp-secret-key {
+ background-color: #fff;
+ color: #333333;
+ font-size: 16px;
+ padding: 10px 0;
+}
+
+/* OAuth */
+
+#kc-oauth h3 {
+ margin-top: 0;
+}
+
+#kc-oauth ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+#kc-oauth ul li {
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
+ font-size: 12px;
+ padding: 10px 0;
+}
+
+#kc-oauth ul li:first-of-type {
+ border-top: 0;
+}
+
+#kc-oauth .kc-role {
+ display: inline-block;
+ width: 50%;
+}
+
+/* Code */
+#kc-code textarea {
+ width: 100%;
+ height: 8em;
+}
+
+/* Social */
+.kc-social-links {
+ margin-top: 20px;
+}
+
+.kc-social-links li {
+ width: 100%;
+}
+
+.kc-social-provider-logo {
+ font-size: 23px;
+ width: 30px;
+ height: 25px;
+ float: left;
+}
+
+.kc-social-gray {
+ color: var(--pf-global--Color--200);
+}
+
+.kc-social-gray h2 {
+ font-size: 1em;
+}
+
+.kc-social-item {
+ margin-bottom: var(--pf-global--spacer--sm);
+ font-size: 15px;
+ text-align: center;
+}
+
+.kc-social-provider-name {
+ position: relative;
+}
+
+.kc-social-icon-text {
+ left: -15px;
+}
+
+.kc-social-grid {
+ display:grid;
+ grid-column-gap: 10px;
+ grid-row-gap: 5px;
+ grid-column-end: span 6;
+ --pf-l-grid__item--GridColumnEnd: span 6;
+}
+
+.kc-social-grid .kc-social-icon-text {
+ left: -10px;
+}
+
+.kc-login-tooltip {
+ position: relative;
+ display: inline-block;
+}
+
+.kc-social-section {
+ text-align: center;
+}
+
+.kc-social-section hr{
+ margin-bottom: 10px
+}
+
+.kc-login-tooltip .kc-tooltip-text{
+ top:-3px;
+ left:160%;
+ background-color: black;
+ visibility: hidden;
+ color: #fff;
+
+ min-width:130px;
+ text-align: center;
+ border-radius: 2px;
+ box-shadow:0 1px 8px rgba(0,0,0,0.6);
+ padding: 5px;
+
+ position: absolute;
+ opacity:0;
+ transition:opacity 0.5s;
+}
+
+/* Show tooltip */
+.kc-login-tooltip:hover .kc-tooltip-text {
+ visibility: visible;
+ opacity:0.7;
+}
+
+/* Arrow for tooltip */
+.kc-login-tooltip .kc-tooltip-text::after {
+ content: " ";
+ position: absolute;
+ top: 15px;
+ right: 100%;
+ margin-top: -5px;
+ border-width: 5px;
+ border-style: solid;
+ border-color: transparent black transparent transparent;
+}
+
+@media (min-width: 768px) {
+ #kc-container-wrapper {
+ position: absolute;
+ width: 100%;
+ }
+
+ .login-pf .container {
+ padding-right: 80px;
+ }
+
+ #kc-locale {
+ position: relative;
+ text-align: right;
+ z-index: 9999;
+ }
+}
+
+@media (max-width: 767px) {
+
+ .login-pf body {
+ background: rgb(255, 255, 255);
+ }
+
+ #kc-header {
+ padding-left: 15px;
+ padding-right: 15px;
+ float: none;
+ text-align: left;
+ }
+
+ #kc-header-wrapper {
+ font-size: 16px;
+ font-weight: bold;
+ padding: 20px 60px 0 0;
+ color: #72767b;
+ letter-spacing: 0;
+ }
+
+ div.kc-logo-text {
+ margin: 0;
+ width: 150px;
+ height: 32px;
+ background-size: 100%;
+ }
+
+ #kc-form {
+ float: none;
+ }
+
+ #kc-info-wrapper {
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
+ background-color: transparent;
+ }
+
+ .login-pf .container {
+ padding-top: 15px;
+ padding-bottom: 15px;
+ }
+
+ #kc-locale {
+ position: absolute;
+ width: 200px;
+ top: 20px;
+ right: 20px;
+ text-align: right;
+ z-index: 9999;
+ }
+}
+
+@media (min-height: 646px) {
+ #kc-container-wrapper {
+ bottom: 12%;
+ }
+}
+
+@media (max-height: 645px) {
+ #kc-container-wrapper {
+ padding-top: 50px;
+ top: 20%;
+ }
+}
+
+.card-pf form.form-actions .btn {
+ float: right;
+ margin-left: 10px;
+}
+
+#kc-form-buttons {
+ margin-top: 20px;
+}
+
+.login-pf-page .login-pf-brand {
+ margin-top: 20px;
+ max-width: 360px;
+ width: 40%;
+}
+
+.select-auth-box-arrow{
+ display: flex;
+ align-items: center;
+ margin-right: 2rem;
+}
+
+.select-auth-box-icon{
+ display: flex;
+ flex: 0 0 2em;
+ justify-content: center;
+ margin-right: 1rem;
+ margin-left: 3rem;
+}
+
+.select-auth-box-parent{
+ border-top: 1px solid var(--pf-global--palette--black-200);
+ padding-top: 1rem;
+ padding-bottom: 1rem;
+ cursor: pointer;
+ text-align: left;
+ align-items: unset;
+ background-color: unset;
+ border-right: unset;
+ border-bottom: unset;
+ border-left: unset;
+}
+
+.select-auth-box-parent:hover{
+ background-color: #f7f8f8;
+}
+
+.select-auth-container {
+ padding-bottom: 0px !important;
+}
+
+.select-auth-box-headline {
+ font-size: var(--pf-global--FontSize--md);
+ color: var(--pf-global--primary-color--100);
+ font-weight: bold;
+}
+
+.select-auth-box-desc {
+ font-size: var(--pf-global--FontSize--sm);
+}
+
+.select-auth-box-paragraph {
+ text-align: center;
+ font-size: var(--pf-global--FontSize--md);
+ margin-bottom: 5px;
+}
+
+.card-pf {
+ margin: 0 auto;
+ box-shadow: var(--pf-global--BoxShadow--lg);
+ padding: 0 20px;
+ max-width: 500px;
+ border-top: 4px solid;
+ border-color: var(--pf-global--primary-color--100);
+}
+
+/*phone*/
+@media (max-width: 767px) {
+ .login-pf-page .card-pf {
+ max-width: none;
+ margin-left: 0;
+ margin-right: 0;
+ padding-top: 0;
+ border-top: 0;
+ box-shadow: 0 0;
+ }
+
+ .kc-social-grid {
+ grid-column-end: 12;
+ --pf-l-grid__item--GridColumnEnd: span 12;
+ }
+
+ .kc-social-grid .kc-social-icon-text {
+ left: -15px;
+ }
+}
+
+.login-pf-page .login-pf-signup {
+ font-size: 15px;
+ color: #72767b;
+}
+#kc-content-wrapper .row {
+ margin-left: 0;
+ margin-right: 0;
+}
+
+.login-pf-page.login-pf-page-accounts {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.login-pf-page .btn-primary {
+ margin-top: 0;
+}
+
+.login-pf-page .list-view-pf .list-group-item {
+ border-bottom: 1px solid #ededed;
+}
+
+.login-pf-page .list-view-pf-description {
+ width: 100%;
+}
+
+#kc-form-login div.form-group:last-of-type,
+#kc-register-form div.form-group:last-of-type,
+#kc-update-profile-form div.form-group:last-of-type,
+#kc-update-email-form div.form-group:last-of-type{
+ margin-bottom: 0px;
+}
+
+.no-bottom-margin {
+ margin-bottom: 0;
+}
+
+#kc-back {
+ margin-top: 5px;
+}
+
+/* Recovery codes */
+.kc-recovery-codes-warning {
+ margin-bottom: 32px;
+}
+.kc-recovery-codes-warning .pf-c-alert__description p {
+ font-size: 0.875rem;
+}
+.kc-recovery-codes-list {
+ list-style: none;
+ columns: 2;
+ margin: 16px 0;
+ padding: 16px 16px 8px 16px;
+ border: 1px solid #D2D2D2;
+}
+.kc-recovery-codes-list li {
+ margin-bottom: 8px;
+ font-size: 11px;
+}
+.kc-recovery-codes-list li span {
+ color: #6A6E73;
+ width: 16px;
+ text-align: right;
+ display: inline-block;
+ margin-right: 1px;
+}
+
+.kc-recovery-codes-actions {
+ margin-bottom: 24px;
+}
+.kc-recovery-codes-actions button {
+ padding-left: 0;
+}
+.kc-recovery-codes-actions button i {
+ margin-right: 8px;
+}
+
+.kc-recovery-codes-confirmation {
+ align-items: baseline;
+ margin-bottom: 16px;
+}
+
+#certificate_subjectDN {
+ overflow-wrap: break-word
+}
+/* End Recovery codes */
diff --git a/assets/keycloak/themes/opea/login/resources/img/OPEA_Studio_bg.jpg b/assets/keycloak/themes/opea/login/resources/img/OPEA_Studio_bg.jpg
new file mode 100644
index 0000000..29a6928
Binary files /dev/null and b/assets/keycloak/themes/opea/login/resources/img/OPEA_Studio_bg.jpg differ
diff --git a/assets/keycloak/themes/opea/login/resources/img/favicon.ico b/assets/keycloak/themes/opea/login/resources/img/favicon.ico
new file mode 100644
index 0000000..bf51bcc
Binary files /dev/null and b/assets/keycloak/themes/opea/login/resources/img/favicon.ico differ
diff --git a/assets/keycloak/themes/opea/login/theme.properties b/assets/keycloak/themes/opea/login/theme.properties
new file mode 100644
index 0000000..3f3eeeb
--- /dev/null
+++ b/assets/keycloak/themes/opea/login/theme.properties
@@ -0,0 +1,4 @@
+parent=keycloak
+import=common/keycloak
+
+styles=css/styles.css
\ No newline at end of file
diff --git a/setup-scripts/setup-genai-studio/manifests/studio-manifest-aws-ecr.yaml b/setup-scripts/setup-genai-studio/manifests/studio-manifest-aws-ecr.yaml
index d3bc2f5..988d03b 100644
--- a/setup-scripts/setup-genai-studio/manifests/studio-manifest-aws-ecr.yaml
+++ b/setup-scripts/setup-genai-studio/manifests/studio-manifest-aws-ecr.yaml
@@ -20,8 +20,13 @@ data:
# SPDX-License-Identifier: Apache-2.0
server {
- listen 80;
- listen [::]:80;
+ # listen 80;
+ # listen [::]:80;
+ listen 443 ssl;
+ listen [::]:443 ssl;
+
+ ssl_certificate /etc/ssl/tls.crt;
+ ssl_certificate_key /etc/ssl/tls.key;
proxy_connect_timeout 600;
proxy_send_timeout 600;
@@ -34,7 +39,7 @@ data:
resolver_timeout 5s;
location /home {
- root /usr/share/nginx/html; # Use root to serve files from a directory
+ root /usr/share/nginx/html;
index index.html;
}
@@ -71,6 +76,15 @@ data:
proxy_set_header X-Forwarded-Proto $scheme;
}
+ # Location block for keycloak
+ location /auth {
+ proxy_pass https://${KEYCLOAK_DNS}/auth/;
+ proxy_set_header Host $host:30007;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+
# Location block for app-backend
location /v1/app-backend {
# Initialize the variable for namespace
@@ -170,10 +184,11 @@ spec:
selector:
app: studio-nginx
ports:
- - protocol: TCP
- port: 80
- targetPort: 80
- nodePort: 30007
+ - name: https
+ protocol: TCP
+ port: 443
+ targetPort: 443
+ nodePort: 30007
type: NodePort
---
apiVersion: apps/v1
@@ -201,7 +216,7 @@ spec:
envsubst "$(env | grep _DNS= | awk -F= '{print "${"$1"}"}' | tr '\n' ' ')" < /tmp/default.conf > /etc/nginx/conf.d/default.conf
envFrom:
- configMapRef:
- name: internal-dns-config
+ name: studio-config
volumeMounts:
- name: tmp-volume
mountPath: /tmp
@@ -214,6 +229,8 @@ spec:
volumeMounts:
- name: nginx-conf-volume
mountPath: /etc/nginx/conf.d
+ - name: tls
+ mountPath: /etc/ssl
securityContext: {}
volumes:
- name: tmp-volume
@@ -222,6 +239,9 @@ spec:
name: studio-nginx-config
- name: nginx-conf-volume
emptyDir: {}
+ - name: tls
+ secret:
+ secretName: tls-secret
---
apiVersion: v1
kind: Service
@@ -272,6 +292,9 @@ rules:
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "create", "list", "watch"]
+- apiGroups: [""]
+ resources: ["persistentvolumeclaims"]
+ verbs: ["get", "create", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
@@ -322,7 +345,7 @@ spec:
value: ${NO_PROXY}
envFrom:
- configMapRef:
- name: internal-dns-config
+ name: studio-config
ports:
- containerPort: 5000
resources:
@@ -394,4 +417,122 @@ spec:
- name: ecr-registry-secret
volumes:
- name: tmp
- emptyDir: {}
\ No newline at end of file
+ emptyDir: {}
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: keycloak
+ namespace: studio
+ labels:
+ app: keycloak
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: keycloak
+ template:
+ metadata:
+ labels:
+ app: keycloak
+ spec:
+ initContainers:
+ - name: keycloak-assets
+ image: curlimages/curl:latest
+ command: ["/bin/sh", "-c"]
+ args:
+ - |
+ OWNER=$(echo ${KC_ASSETS_GIT_URL} | sed -E 's|https://github.com/([^/]+)/([^/]+)/tree/([^/]+)/.*|\1|')
+ REPO=$(echo ${KC_ASSETS_GIT_URL} | sed -E 's|https://github.com/([^/]+)/([^/]+)/tree/([^/]+)/.*|\2|')
+ BRANCH=$(echo ${KC_ASSETS_GIT_URL} | sed -E 's|https://github.com/[^/]+/[^/]+/tree/([^/]+)/.*|\1|')
+ KC_ASSETS_DIR=$(echo ${KC_ASSETS_GIT_URL} | sed -E 's|https://github.com/[^/]+/[^/]+/tree/[^/]+/(.*?)/?$|\1|')
+ if [[ "${KC_ASSETS_DIR: -1}" == "/" ]]; then KC_ASSETS_DIR="${KC_ASSETS_DIR%/}"; fi
+ DOWNLOAD_URL="https://codeload.github.com/${OWNER}/${REPO}/tar.gz/${BRANCH}"
+ curl "${DOWNLOAD_URL}" | tar -xz --strip-components=4 -C /opt/keycloak/themes "${REPO}-${BRANCH}/${KC_ASSETS_DIR}/themes"
+ curl "${DOWNLOAD_URL}" | tar -xz --strip-components=4 -C /opt/keycloak/data "${REPO}-${BRANCH}/${KC_ASSETS_DIR}/data"
+ envFrom:
+ - configMapRef:
+ name: studio-config
+ volumeMounts:
+ - name: keycloak-themes-volume
+ mountPath: /opt/keycloak/themes
+ - name: keycloak-dataimport-volume
+ mountPath: /opt/keycloak/data/import
+ securityContext:
+ runAsUser: 0
+ runAsGroup: 0
+ containers:
+ - name: keycloak
+ image: quay.io/keycloak/keycloak:latest
+ volumeMounts:
+ - name: tls
+ mountPath: /etc/ssl
+ readOnly: true
+ - name: keycloak-themes-volume
+ mountPath: /opt/keycloak/themes
+ - name: keycloak-dataimport-volume
+ mountPath: /opt/keycloak/data/import
+ args:
+ - start
+ - --import-realm
+ ports:
+ - containerPort: 8080
+ - containerPort: 8443
+ env:
+ - name: KC_BOOTSTRAP_ADMIN_USERNAME
+ value: "admin"
+ - name: KC_BOOTSTRAP_ADMIN_PASSWORD
+ value: "admin"
+ - name: KC_PROXY_HEADERS
+ value: "forwarded"
+ - name: KC_HTTP_RELATIVE_PATH
+ value: "/auth"
+ - name: KC_PROXY
+ value: edge
+ - name: KC_HTTPS_CERTIFICATE_FILE
+ value: /etc/ssl/tls.crt
+ - name: KC_HTTPS_CERTIFICATE_KEY_FILE
+ value: /etc/ssl/tls.key
+ - name: KC_HOSTNAME_STRICT
+ value: "false"
+ - name: KC_HOSTNAME_STRICT_HTTPS
+ value: "true"
+ readinessProbe:
+ failureThreshold: 3
+ httpGet:
+ path: auth/realms/master
+ port: 8443
+ scheme: HTTPS
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 1
+ resources:
+ requests:
+ memory: "512Mi"
+ cpu: "500m"
+ limits:
+ memory: "1Gi"
+ cpu: "1"
+ volumes:
+ - name: tls
+ secret:
+ secretName: tls-secret
+ - name: keycloak-themes-volume
+ emptyDir: {}
+ - name: keycloak-dataimport-volume
+ emptyDir: {}
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: keycloak
+ namespace: studio
+spec:
+ type: ClusterIP
+ ports:
+ - name: https
+ protocol: TCP
+ port: 8443
+ targetPort: 8443
+ selector:
+ app: keycloak
\ No newline at end of file
diff --git a/setup-scripts/setup-genai-studio/manifests/studio-manifest.yaml b/setup-scripts/setup-genai-studio/manifests/studio-manifest.yaml
index 5885f11..ea9945e 100644
--- a/setup-scripts/setup-genai-studio/manifests/studio-manifest.yaml
+++ b/setup-scripts/setup-genai-studio/manifests/studio-manifest.yaml
@@ -10,8 +10,13 @@ data:
# SPDX-License-Identifier: Apache-2.0
server {
- listen 80;
- listen [::]:80;
+ # listen 80;
+ # listen [::]:80;
+ listen 443 ssl;
+ listen [::]:443 ssl;
+
+ ssl_certificate /etc/ssl/app-tls.crt;
+ ssl_certificate_key /etc/ssl/app-tls.key;
proxy_connect_timeout 600;
proxy_send_timeout 600;
@@ -24,7 +29,7 @@ data:
resolver_timeout 5s;
location /home {
- root /usr/share/nginx/html; # Use root to serve files from a directory
+ root /usr/share/nginx/html;
index index.html;
}
@@ -61,6 +66,15 @@ data:
proxy_set_header X-Forwarded-Proto $scheme;
}
+ # Location block for keycloak
+ location /auth {
+ proxy_pass https://${KEYCLOAK_DNS}/auth/;
+ proxy_set_header Host $host:30007;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+
# Location block for app-backend
location /v1/app-backend {
# Initialize the variable for namespace
@@ -160,10 +174,11 @@ spec:
selector:
app: studio-nginx
ports:
- - protocol: TCP
- port: 80
- targetPort: 80
- nodePort: 30007
+ - name: https
+ protocol: TCP
+ port: 443
+ targetPort: 443
+ nodePort: 30007
type: NodePort
---
apiVersion: apps/v1
@@ -191,7 +206,7 @@ spec:
envsubst "$(env | grep _DNS= | awk -F= '{print "${"$1"}"}' | tr '\n' ' ')" < /tmp/default.conf > /etc/nginx/conf.d/default.conf
envFrom:
- configMapRef:
- name: internal-dns-config
+ name: studio-config
volumeMounts:
- name: tmp-volume
mountPath: /tmp
@@ -204,6 +219,8 @@ spec:
volumeMounts:
- name: nginx-conf-volume
mountPath: /etc/nginx/conf.d
+ - name: app-tls
+ mountPath: /etc/ssl
securityContext: {}
volumes:
- name: tmp-volume
@@ -212,6 +229,9 @@ spec:
name: studio-nginx-config
- name: nginx-conf-volume
emptyDir: {}
+ - name: app-tls
+ secret:
+ secretName: app-tls
---
apiVersion: v1
kind: Service
@@ -262,6 +282,9 @@ rules:
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "create", "list", "watch"]
+- apiGroups: [""]
+ resources: ["persistentvolumeclaims"]
+ verbs: ["get", "create", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
@@ -312,7 +335,7 @@ spec:
value: ${NO_PROXY}
envFrom:
- configMapRef:
- name: internal-dns-config
+ name: studio-config
ports:
- containerPort: 5000
resources:
@@ -370,6 +393,21 @@ spec:
securityContext: {}
image: ${REGISTRY}/studio-frontend:${TAG}
imagePullPolicy: Always
+ env:
+ - name: DATABASE_TYPE
+ value: mysql
+ - name: DATABASE_HOST
+ value: ${MYSQL_HOST}
+ - name: DATABASE_PORT
+ value: "3306"
+ - name: DATABASE_USER
+ value: studio
+ - name: DATABASE_PASSWORD
+ value: studio
+ - name: DATABASE_NAME
+ value: studio
+ - name: DATABASE_SSL
+ value: "true"
ports:
- name: studio-frontend
containerPort: 8080
@@ -378,6 +416,147 @@ spec:
volumeMounts:
- mountPath: /tmp
name: tmp
+ - name: mysql-tls
+ mountPath: /etc/mysql/ssl
+ readOnly: true
volumes:
- name: tmp
- emptyDir: {}
\ No newline at end of file
+ emptyDir: {}
+ - name: mysql-tls
+ secret:
+ secretName: mysql-tls
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: keycloak
+ namespace: studio
+ labels:
+ app: keycloak
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: keycloak
+ template:
+ metadata:
+ labels:
+ app: keycloak
+ spec:
+ initContainers:
+ - name: keycloak-assets
+ image: curlimages/curl:latest
+ command: ["/bin/sh", "-c"]
+ args:
+ - |
+ OWNER=$(echo ${KC_ASSETS_GIT_URL} | sed -E 's|https://github.com/([^/]+)/([^/]+)/tree/([^/]+)/.*|\1|')
+ REPO=$(echo ${KC_ASSETS_GIT_URL} | sed -E 's|https://github.com/([^/]+)/([^/]+)/tree/([^/]+)/.*|\2|')
+ BRANCH=$(echo ${KC_ASSETS_GIT_URL} | sed -E 's|https://github.com/[^/]+/[^/]+/tree/([^/]+)/.*|\1|')
+ KC_ASSETS_DIR=$(echo ${KC_ASSETS_GIT_URL} | sed -E 's|https://github.com/[^/]+/[^/]+/tree/[^/]+/(.*?)/?$|\1|')
+ if [[ "${KC_ASSETS_DIR: -1}" == "/" ]]; then KC_ASSETS_DIR="${KC_ASSETS_DIR%/}"; fi
+ DOWNLOAD_URL="https://codeload.github.com/${OWNER}/${REPO}/tar.gz/${BRANCH}"
+ curl "${DOWNLOAD_URL}" | tar -xz --strip-components=4 -C /opt/keycloak/themes "${REPO}-${BRANCH}/${KC_ASSETS_DIR}/themes"
+ curl "${DOWNLOAD_URL}" | tar -xz --strip-components=4 -C /opt/keycloak/data "${REPO}-${BRANCH}/${KC_ASSETS_DIR}/data"
+ envFrom:
+ - configMapRef:
+ name: studio-config
+ volumeMounts:
+ - name: keycloak-themes-volume
+ mountPath: /opt/keycloak/themes
+ - name: keycloak-dataimport-volume
+ mountPath: /opt/keycloak/data/import
+ securityContext:
+ runAsUser: 0
+ runAsGroup: 0
+ containers:
+ - name: keycloak
+ image: quay.io/keycloak/keycloak:latest
+ volumeMounts:
+ - name: mysql-tls
+ mountPath: /etc/mysql/ssl
+ readOnly: true
+ - name: app-tls
+ mountPath: /etc/ssl
+ readOnly: true
+ - name: keycloak-themes-volume
+ mountPath: /opt/keycloak/themes
+ - name: keycloak-dataimport-volume
+ mountPath: /opt/keycloak/data/import
+ args:
+ - start
+ - --import-realm
+ ports:
+ - containerPort: 8080
+ - containerPort: 8443
+ env:
+ - name: KC_BOOTSTRAP_ADMIN_USERNAME
+ value: "admin"
+ - name: KC_BOOTSTRAP_ADMIN_PASSWORD
+ value: "admin"
+ - name: KC_PROXY_HEADERS
+ value: "forwarded"
+ - name: KC_HTTP_RELATIVE_PATH
+ value: "/auth"
+ - name: KC_PROXY
+ value: edge
+ - name: KC_HTTPS_CERTIFICATE_FILE
+ value: /etc/ssl/app-tls.crt
+ - name: KC_HTTPS_CERTIFICATE_KEY_FILE
+ value: /etc/ssl/app-tls.key
+ - name: KC_HOSTNAME_STRICT
+ value: "false"
+ - name: KC_HOSTNAME_STRICT_HTTPS
+ value: "true"
+ # Database Configuration for MySQL
+ - name: KC_DB
+ value: "mysql"
+ - name: KC_DB_URL
+ value: "jdbc:mysql://${MYSQL_HOST}:3306/keycloak?useSSL=true&requireSSL=true&clientCertificateKeyStoreUrl=file:/etc/mysql/ssl/client-keystore.p12&trustCertificateKeyStoreUrl=file:/etc/mysql/ssl/ca.pem"
+ - name: KC_DB_USERNAME
+ value: "studio"
+ - name: KC_DB_PASSWORD
+ value: "studio"
+ - name: KC_DB_DATABASE
+ value: "keycloak"
+ readinessProbe:
+ failureThreshold: 3
+ httpGet:
+ path: auth/realms/master
+ port: 8443
+ scheme: HTTPS
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 1
+ resources:
+ requests:
+ memory: "512Mi"
+ cpu: "500m"
+ limits:
+ memory: "1Gi"
+ cpu: "1"
+ volumes:
+ - name: app-tls
+ secret:
+ secretName: app-tls
+ - name: mysql-tls
+ secret:
+ secretName: mysql-tls
+ - name: keycloak-themes-volume
+ emptyDir: {}
+ - name: keycloak-dataimport-volume
+ emptyDir: {}
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: keycloak
+ namespace: studio
+spec:
+ type: ClusterIP
+ ports:
+ - name: https
+ protocol: TCP
+ port: 8443
+ targetPort: 8443
+ selector:
+ app: keycloak
\ No newline at end of file
diff --git a/setup-scripts/setup-genai-studio/playbooks/deploy-studio.yml b/setup-scripts/setup-genai-studio/playbooks/deploy-studio.yml
index 70d2f3a..e1f422a 100644
--- a/setup-scripts/setup-genai-studio/playbooks/deploy-studio.yml
+++ b/setup-scripts/setup-genai-studio/playbooks/deploy-studio.yml
@@ -4,9 +4,14 @@
- ../vars.yml
tasks:
+ - name: Check if studio namespace exists
+ command: kubectl get namespace studio
+ register: studio_namespace
+ ignore_errors: yes
+
- name: Create studio namespace
command: kubectl create namespace studio
- ignore_errors: yes
+ when: studio_namespace.rc != 0
- name: Check for coredns service
shell: kubectl get svc coredns -n kube-system --ignore-not-found
@@ -18,13 +23,61 @@
shell: sed -i 's/kube-dns/coredns/g' ../manifests/studio-manifest.yaml
when: coredns_check.stdout != ''
- - name: Apply internal DNS configuration
- command: kubectl apply -f ../internal-dns-config.yaml
+ - name: Check if app-tls exists in studio namespace
+ command: kubectl get secret app-tls -n studio
+ register: app_tls_secret_check
+ ignore_errors: yes
+
+ - name: Generate TLS certificate and create app-tls
+ shell: |
+ openssl req -x509 -nodes -days 365 -newkey rsa:4096 -keyout app-tls.key -out app-tls.crt -subj "/CN=studio/O=studio"
+ kubectl create secret generic app-tls --from-file=app-tls.crt --from-file=app-tls.key -n studio
+ rm app-tls.key app-tls.crt
+ when: app_tls_secret_check.rc != 0
+
+ - name: Check if mysql-tls exists in studio namespace
+ command: kubectl get secret mysql-tls -n studio
+ register: mysql_tls_secret_check
+ ignore_errors: yes
+
+ - name: Copy mysql ssl to current user
+ become: yes
+ become_user: root
+ shell: |
+ cp /var/lib/mysql/ca.pem .
+ cp /var/lib/mysql/client-cert.pem .
+ cp /var/lib/mysql/client-key.pem .
+ chown -R {{ ansible_env.USER }}:{{ ansible_env.USER }} ca.pem
+ chown -R {{ ansible_env.USER }}:{{ ansible_env.USER }} client-key.pem
+ chown -R {{ ansible_env.USER }}:{{ ansible_env.USER }} client-cert.pem
+ when: mysql_tls_secret_check.rc != 0
+
+ - name: Create mysql-tls from mysql ssl
+ shell: |
+ openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem -out client-keystore.p12 -name keycloak -CAfile ca.pem -caname root -password pass:
+ kubectl create secret generic mysql-tls \
+ --from-file=ca.pem \
+ --from-file=client-cert.pem \
+ --from-file=client-key.pem \
+ --from-file=client-keystore.p12 \
+ -n studio
+ rm ca.pem client-key.pem client-cert.pem client-keystore.p12
+ when: mysql_tls_secret_check.rc != 0
+
+ - name: Apply studio configuration
+ command: kubectl apply -f ../studio-config.yaml
- name: Apply customized studio manifest
- shell: "envsubst '${REGISTRY} ${TAG} ${HTTP_PROXY} ${NO_PROXY}' < ../manifests/studio-manifest.yaml | kubectl apply -f -"
+ shell: "envsubst '${REGISTRY} ${TAG} ${HTTP_PROXY} ${NO_PROXY} ${MYSQL_HOST}' < ../manifests/studio-manifest.yaml | kubectl apply -f -"
environment:
REGISTRY: "{{ container_registry }}"
TAG: "{{ container_tag }}"
HTTP_PROXY: "{{ http_proxy }}"
- NO_PROXY: "{{ no_proxy }}"
\ No newline at end of file
+ NO_PROXY: "{{ no_proxy }}"
+ MYSQL_HOST: "{{ mysql_host }}"
+
+ - name: Wait for all pods to be ready in studio namespace
+ shell: kubectl wait --for=condition=ready pod --all --namespace=studio --timeout=180s
+ register: pod_ready_check
+ failed_when: pod_ready_check.rc != 0
+ changed_when: false
\ No newline at end of file
diff --git a/setup-scripts/setup-genai-studio/playbooks/setup-mysqldb.yml b/setup-scripts/setup-genai-studio/playbooks/setup-mysqldb.yml
new file mode 100644
index 0000000..8b5261a
--- /dev/null
+++ b/setup-scripts/setup-genai-studio/playbooks/setup-mysqldb.yml
@@ -0,0 +1,92 @@
+- name: Setup MySQL Server
+ hosts: localhost
+ become: yes
+ tasks:
+
+ - name: Install PyMySQL module
+ pip:
+ name: PyMySQL
+ state: present
+
+ - name: Check if MySQL user 'studio' exists
+ mysql_user:
+ login_user: root
+ login_password: root
+ name: studio
+ check_implicit_admin: yes
+ state: present
+ register: studio_user_exists
+ ignore_errors: yes
+
+ - name: End playbook if MySQL user 'studio' exists
+ meta: end_play
+ when: studio_user_exists is succeeded
+
+ - name: Install MySQL server
+ apt:
+ name: mysql-server
+ state: present
+ update_cache: yes
+
+ - name: Configure MySQL to listen on all interfaces
+ lineinfile:
+ path: /etc/mysql/mysql.conf.d/mysqld.cnf
+ regexp: '^bind-address'
+ line: 'bind-address = 0.0.0.0'
+ state: present
+
+ - name: Restart MySQL service
+ service:
+ name: mysql
+ state: restarted
+
+ - name: Secure MySQL installation updating root password
+ mysql_user:
+ name: root
+ host: localhost
+ password: root
+ login_unix_socket: /var/run/mysqld/mysqld.sock
+ priv: '*.*:ALL,GRANT'
+ state: present
+ plugin: mysql_native_password
+ ignore_errors: yes
+
+ - name: Create MySQL user 'studio' for all hosts
+ mysql_user:
+ login_user: root
+ login_password: root
+ name: studio
+ host: '%'
+ password: studio
+ priv: '*.*:ALL,GRANT'
+ state: present
+
+ - name: Enforce SSL for MySQL user 'studio' for all hosts
+ mysql_query:
+ login_user: root
+ login_password: root
+ query: "ALTER USER 'studio'@'%' REQUIRE X509;"
+
+ - name: Create MySQL user 'studio' for localhost without X509
+ mysql_user:
+ login_user: root
+ login_password: root
+ name: studio
+ host: localhost
+ password: studio
+ priv: '*.*:ALL,GRANT'
+ state: present
+
+ - name: Create database 'keycloak'
+ mysql_db:
+ login_user: studio
+ login_password: studio
+ name: keycloak
+ state: present
+
+ - name: Create database 'studio'
+ mysql_db:
+ login_user: studio
+ login_password: studio
+ name: studio
+ state: present
\ No newline at end of file
diff --git a/setup-scripts/setup-genai-studio/studio-config.yaml b/setup-scripts/setup-genai-studio/studio-config.yaml
new file mode 100644
index 0000000..002efdf
--- /dev/null
+++ b/setup-scripts/setup-genai-studio/studio-config.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: studio-config
+ namespace: studio
+data:
+ KC_ASSETS_GIT_URL: "https://github.com/opea-project/GenAIStudio/tree/main/assets/keycloak"
+ KEYCLOAK_DNS: "keycloak.studio.svc.cluster.local:8443"
+ GRAFANA_DNS: "kube-prometheus-stack-grafana.monitoring.svc.cluster.local"
+ STUDIO_FRONTEND_DNS: "studio-frontend.studio.svc.cluster.local:3000"
+ APP_FRONTEND_DNS: "app-frontend.$namespace.svc.cluster.local:5175"
+ APP_BACKEND_DNS: "app-backend.$namespace.svc.cluster.local:8888"
+ PREPARE_DOC_REDIS_PREP_DNS: "prepare-doc-redis-prep-0.$namespace.svc.cluster.local:6007"
+ STUDIO_BACKEND_DNS: "studio-backend.studio.svc.cluster.local:5000"
\ No newline at end of file
diff --git a/studio-backend/app/templates/grafana-dashboards/sandbox-dashboard.json b/studio-backend/app/templates/grafana-dashboards/sandbox-dashboard.json
index 36eced1..e84fc3f 100644
--- a/studio-backend/app/templates/grafana-dashboards/sandbox-dashboard.json
+++ b/studio-backend/app/templates/grafana-dashboards/sandbox-dashboard.json
@@ -22,104 +22,138 @@
"id": null,
"links": [],
"panels": [
+ {
+ "collapsed": false,
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 0
+ },
+ "id": 2,
+ "panels": [],
+ "title": "Cluster CPU / MEM / DISK",
+ "type": "row"
+ },
{
"datasource": {
"default": true,
"type": "prometheus",
"uid": "prometheus"
},
+ "description": "Resource pressure via PSI",
"fieldConfig": {
"defaults": {
"color": {
- "mode": "palette-classic"
- },
- "custom": {
- "axisBorderShow": false,
- "axisCenteredZero": false,
- "axisColorMode": "text",
- "axisLabel": "",
- "axisPlacement": "auto",
- "barAlignment": 0,
- "barWidthFactor": 0.6,
- "drawStyle": "line",
- "fillOpacity": 10,
- "gradientMode": "none",
- "hideFrom": {
- "legend": false,
- "tooltip": false,
- "viz": false
- },
- "insertNulls": false,
- "lineInterpolation": "linear",
- "lineWidth": 1,
- "pointSize": 5,
- "scaleDistribution": {
- "type": "linear"
- },
- "showPoints": "never",
- "spanNulls": false,
- "stacking": {
- "group": "A",
- "mode": "none"
- },
- "thresholdsStyle": {
- "mode": "off"
- }
+ "mode": "thresholds"
},
+ "decimals": 1,
+ "links": [],
"mappings": [],
+ "max": 1,
+ "min": 0,
"thresholds": {
- "mode": "absolute",
+ "mode": "percentage",
"steps": [
{
"color": "green",
"value": null
},
{
- "color": "red",
- "value": 80
+ "color": "dark-yellow",
+ "value": 70
+ },
+ {
+ "color": "dark-red",
+ "value": 90
}
]
},
- "unit": "short"
+ "unit": "percentunit"
},
"overrides": []
},
"gridPos": {
- "h": 9,
- "w": 12,
+ "h": 4,
+ "w": 3,
"x": 0,
- "y": 0
+ "y": 1
},
- "id": 2,
+ "id": 3,
"options": {
- "legend": {
- "calcs": [],
- "displayMode": "list",
- "placement": "bottom",
- "showLegend": true
+ "displayMode": "basic",
+ "maxVizHeight": 300,
+ "minVizHeight": 10,
+ "minVizWidth": 0,
+ "namePlacement": "auto",
+ "orientation": "horizontal",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
},
- "tooltip": {
- "mode": "multi",
- "sort": "none"
- }
+ "showUnfilled": true,
+ "sizing": "auto",
+ "text": {},
+ "valueMode": "color"
},
- "pluginVersion": "8.0.0",
+ "pluginVersion": "11.2.0",
"targets": [
{
"datasource": {
"type": "prometheus",
- "uid": "prometheus"
+ "uid": "${datasource}"
},
"editorMode": "code",
- "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"___EXPR_NAMESPACE___\", container!=\"\"}[5m])) by (pod)",
- "interval": "",
- "legendFormat": "{{pod}}",
- "range": true,
- "refId": "A"
+ "exemplar": false,
+ "expr": "irate(node_pressure_cpu_waiting_seconds_total{job=\"node-exporter\"}[$__rate_interval])",
+ "format": "time_series",
+ "instant": true,
+ "intervalFactor": 1,
+ "legendFormat": "CPU",
+ "range": false,
+ "refId": "CPU some",
+ "step": 240
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${datasource}"
+ },
+ "editorMode": "code",
+ "exemplar": false,
+ "expr": "irate(node_pressure_memory_waiting_seconds_total{job=\"node-exporter\"}[$__rate_interval])",
+ "format": "time_series",
+ "hide": false,
+ "instant": true,
+ "intervalFactor": 1,
+ "legendFormat": "Mem",
+ "range": false,
+ "refId": "Memory some",
+ "step": 240
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${datasource}"
+ },
+ "editorMode": "code",
+ "exemplar": false,
+ "expr": "irate(node_pressure_io_waiting_seconds_total{job=\"node-exporter\"}[$__rate_interval])",
+ "format": "time_series",
+ "hide": false,
+ "instant": true,
+ "intervalFactor": 1,
+ "legendFormat": "I/O",
+ "range": false,
+ "refId": "I/O some",
+ "step": 240
}
],
- "title": "CPU Usage (container)",
- "type": "timeseries"
+ "title": "Pressure",
+ "type": "bargauge"
},
{
"datasource": {
@@ -127,98 +161,90 @@
"type": "prometheus",
"uid": "prometheus"
},
+ "description": "Busy state of all CPU cores together",
"fieldConfig": {
"defaults": {
"color": {
- "mode": "palette-classic"
+ "mode": "thresholds"
},
- "custom": {
- "axisBorderShow": false,
- "axisCenteredZero": false,
- "axisColorMode": "text",
- "axisLabel": "",
- "axisPlacement": "auto",
- "barAlignment": 0,
- "barWidthFactor": 0.6,
- "drawStyle": "line",
- "fillOpacity": 10,
- "gradientMode": "none",
- "hideFrom": {
- "legend": false,
- "tooltip": false,
- "viz": false
- },
- "insertNulls": false,
- "lineInterpolation": "linear",
- "lineWidth": 1,
- "pointSize": 5,
- "scaleDistribution": {
- "type": "linear"
- },
- "showPoints": "never",
- "spanNulls": false,
- "stacking": {
- "group": "A",
- "mode": "none"
- },
- "thresholdsStyle": {
- "mode": "off"
+ "decimals": 1,
+ "mappings": [
+ {
+ "options": {
+ "match": "null",
+ "result": {
+ "text": "N/A"
+ }
+ },
+ "type": "special"
}
- },
- "mappings": [],
+ ],
+ "max": 100,
+ "min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
- "color": "green",
+ "color": "rgba(50, 172, 45, 0.97)",
"value": null
},
{
- "color": "red",
- "value": 80
+ "color": "rgba(237, 129, 40, 0.89)",
+ "value": 85
+ },
+ {
+ "color": "rgba(245, 54, 54, 0.9)",
+ "value": 95
}
]
},
- "unit": "bytes"
+ "unit": "percent"
},
"overrides": []
},
"gridPos": {
- "h": 9,
- "w": 12,
- "x": 12,
- "y": 0
+ "h": 4,
+ "w": 3,
+ "x": 3,
+ "y": 1
},
"id": 4,
"options": {
- "legend": {
- "calcs": [],
- "displayMode": "list",
- "placement": "bottom",
- "showLegend": true
+ "minVizHeight": 75,
+ "minVizWidth": 75,
+ "orientation": "auto",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
},
- "tooltip": {
- "mode": "multi",
- "sort": "none"
- }
+ "showThresholdLabels": false,
+ "showThresholdMarkers": true,
+ "sizing": "auto"
},
- "pluginVersion": "8.0.0",
+ "pluginVersion": "11.2.0",
"targets": [
{
"datasource": {
"type": "prometheus",
- "uid": "prometheus"
+ "uid": "${datasource}"
},
"editorMode": "code",
- "expr": "sum(rate(container_memory_usage_bytes{namespace=\"___EXPR_NAMESPACE___\", container!=\"\"}[5m])) by (pod)",
- "interval": "",
- "legendFormat": "{{pod}}",
- "range": true,
- "refId": "B"
+ "exemplar": false,
+ "expr": "100 * (1 - avg(rate(node_cpu_seconds_total{mode=\"idle\"}[$__rate_interval])))",
+ "hide": false,
+ "instant": true,
+ "intervalFactor": 1,
+ "legendFormat": "",
+ "range": false,
+ "refId": "A",
+ "step": 240
}
],
- "title": "Memory Usage (container)",
- "type": "timeseries"
+ "title": "CPU Busy",
+ "type": "gauge"
},
{
"datasource": {
@@ -226,98 +252,90 @@
"type": "prometheus",
"uid": "prometheus"
},
+ "description": "System load over all CPU cores together",
"fieldConfig": {
"defaults": {
"color": {
- "mode": "palette-classic"
+ "mode": "thresholds"
},
- "custom": {
- "axisBorderShow": false,
- "axisCenteredZero": false,
- "axisColorMode": "text",
- "axisLabel": "",
- "axisPlacement": "auto",
- "barAlignment": 0,
- "barWidthFactor": 0.6,
- "drawStyle": "line",
- "fillOpacity": 10,
- "gradientMode": "none",
- "hideFrom": {
- "legend": false,
- "tooltip": false,
- "viz": false
- },
- "insertNulls": false,
- "lineInterpolation": "linear",
- "lineWidth": 1,
- "pointSize": 5,
- "scaleDistribution": {
- "type": "linear"
- },
- "showPoints": "never",
- "spanNulls": false,
- "stacking": {
- "group": "A",
- "mode": "none"
- },
- "thresholdsStyle": {
- "mode": "off"
+ "decimals": 1,
+ "mappings": [
+ {
+ "options": {
+ "match": "null",
+ "result": {
+ "text": "N/A"
+ }
+ },
+ "type": "special"
}
- },
- "mappings": [],
+ ],
+ "max": 100,
+ "min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
- "color": "green",
+ "color": "rgba(50, 172, 45, 0.97)",
"value": null
},
{
- "color": "red",
- "value": 80
+ "color": "rgba(237, 129, 40, 0.89)",
+ "value": 85
+ },
+ {
+ "color": "rgba(245, 54, 54, 0.9)",
+ "value": 95
}
]
},
- "unit": "short"
+ "unit": "percent"
},
"overrides": []
},
"gridPos": {
- "h": 9,
- "w": 12,
- "x": 0,
- "y": 9
+ "h": 4,
+ "w": 3,
+ "x": 6,
+ "y": 1
},
"id": 5,
"options": {
- "legend": {
- "calcs": [],
- "displayMode": "list",
- "placement": "bottom",
- "showLegend": true
+ "minVizHeight": 75,
+ "minVizWidth": 75,
+ "orientation": "auto",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
},
- "tooltip": {
- "mode": "multi",
- "sort": "none"
- }
+ "showThresholdLabels": false,
+ "showThresholdMarkers": true,
+ "sizing": "auto"
},
- "pluginVersion": "8.0.0",
+ "pluginVersion": "11.2.0",
"targets": [
{
"datasource": {
"type": "prometheus",
- "uid": "prometheus"
+ "uid": "${datasource}"
},
"editorMode": "code",
- "expr": "rate(process_cpu_seconds_total{namespace=\"___EXPR_NAMESPACE___\"}[5m])",
- "interval": "",
- "legendFormat": "{{pod}}",
- "range": true,
- "refId": "A"
+ "exemplar": false,
+ "expr": "scalar(node_load1{job=\"node-exporter\"}) * 100 / count(count(node_cpu_seconds_total{job=\"node-exporter\"}) by (cpu))",
+ "format": "time_series",
+ "hide": false,
+ "instant": true,
+ "intervalFactor": 1,
+ "range": false,
+ "refId": "A",
+ "step": 240
}
],
- "title": "CPU Usage (process)",
- "type": "timeseries"
+ "title": "Sys Load",
+ "type": "gauge"
},
{
"datasource": {
@@ -325,100 +343,3804 @@
"type": "prometheus",
"uid": "prometheus"
},
+ "description": "Non available RAM memory",
"fieldConfig": {
"defaults": {
"color": {
- "mode": "palette-classic"
- },
- "custom": {
- "axisBorderShow": false,
- "axisCenteredZero": false,
- "axisColorMode": "text",
- "axisLabel": "",
- "axisPlacement": "auto",
- "barAlignment": 0,
- "barWidthFactor": 0.6,
- "drawStyle": "line",
- "fillOpacity": 10,
- "gradientMode": "none",
- "hideFrom": {
- "legend": false,
- "tooltip": false,
- "viz": false
- },
- "insertNulls": false,
- "lineInterpolation": "linear",
- "lineWidth": 1,
- "pointSize": 5,
- "scaleDistribution": {
- "type": "linear"
- },
- "showPoints": "never",
- "spanNulls": false,
- "stacking": {
- "group": "A",
- "mode": "none"
- },
- "thresholdsStyle": {
- "mode": "off"
- }
+ "mode": "thresholds"
},
+ "decimals": 1,
"mappings": [],
+ "max": 100,
+ "min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
- "color": "green",
+ "color": "rgba(50, 172, 45, 0.97)",
"value": null
},
{
- "color": "red",
+ "color": "rgba(237, 129, 40, 0.89)",
"value": 80
+ },
+ {
+ "color": "rgba(245, 54, 54, 0.9)",
+ "value": 90
}
]
},
- "unit": "short"
+ "unit": "percent"
},
"overrides": []
},
"gridPos": {
- "h": 9,
- "w": 12,
- "x": 12,
- "y": 9
+ "h": 4,
+ "w": 3,
+ "x": 9,
+ "y": 1
},
+ "hideTimeOverride": false,
"id": 6,
"options": {
- "legend": {
- "calcs": [],
- "displayMode": "list",
- "placement": "bottom",
- "showLegend": true
+ "minVizHeight": 75,
+ "minVizWidth": 75,
+ "orientation": "auto",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
},
- "tooltip": {
- "mode": "multi",
- "sort": "none"
- }
+ "showThresholdLabels": false,
+ "showThresholdMarkers": true,
+ "sizing": "auto"
},
- "pluginVersion": "8.0.0",
+ "pluginVersion": "11.2.0",
"targets": [
{
"datasource": {
"type": "prometheus",
- "uid": "prometheus"
+ "uid": "${datasource}"
},
"editorMode": "code",
- "expr": "rate(process_resident_memory_bytes{namespace=\"___EXPR_NAMESPACE___\"}[5m])",
+ "exemplar": false,
+ "expr": "((node_memory_MemTotal_bytes{ job=\"node-exporter\"} - node_memory_MemFree_bytes{ job=\"node-exporter\"}) / node_memory_MemTotal_bytes{ job=\"node-exporter\"}) * 100",
+ "format": "time_series",
+ "hide": true,
+ "instant": true,
+ "intervalFactor": 1,
+ "range": false,
+ "refId": "A",
+ "step": 240
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${datasource}"
+ },
+ "editorMode": "code",
+ "exemplar": false,
+ "expr": "(1 - (node_memory_MemAvailable_bytes{ job=\"node-exporter\"} / node_memory_MemTotal_bytes{ job=\"node-exporter\"})) * 100",
+ "format": "time_series",
+ "hide": false,
+ "instant": true,
+ "intervalFactor": 1,
+ "range": false,
+ "refId": "B",
+ "step": 240
+ }
+ ],
+ "title": "RAM Used",
+ "type": "gauge"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "description": "Used Swap",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "decimals": 1,
+ "mappings": [
+ {
+ "options": {
+ "match": "null",
+ "result": {
+ "text": "N/A"
+ }
+ },
+ "type": "special"
+ }
+ ],
+ "max": 100,
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "rgba(50, 172, 45, 0.97)",
+ "value": null
+ },
+ {
+ "color": "rgba(237, 129, 40, 0.89)",
+ "value": 10
+ },
+ {
+ "color": "rgba(245, 54, 54, 0.9)",
+ "value": 25
+ }
+ ]
+ },
+ "unit": "percent"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 4,
+ "w": 3,
+ "x": 12,
+ "y": 1
+ },
+ "id": 7,
+ "options": {
+ "minVizHeight": 75,
+ "minVizWidth": 75,
+ "orientation": "auto",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showThresholdLabels": false,
+ "showThresholdMarkers": true,
+ "sizing": "auto"
+ },
+ "pluginVersion": "11.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${datasource}"
+ },
+ "editorMode": "code",
+ "exemplar": false,
+ "expr": "((node_memory_SwapTotal_bytes{job=\"node-exporter\"} - node_memory_SwapFree_bytes{job=\"node-exporter\"}) / (node_memory_SwapTotal_bytes{job=\"node-exporter\"})) * 100",
+ "instant": true,
+ "intervalFactor": 1,
+ "range": false,
+ "refId": "A",
+ "step": 240
+ }
+ ],
+ "title": "SWAP Used",
+ "type": "gauge"
+ },
+ {
+ "datasource": {},
+ "description": "Used Root FS",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "decimals": 1,
+ "mappings": [
+ {
+ "options": {
+ "match": "null",
+ "result": {
+ "text": "N/A"
+ }
+ },
+ "type": "special"
+ }
+ ],
+ "max": 100,
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "rgba(50, 172, 45, 0.97)",
+ "value": null
+ },
+ {
+ "color": "rgba(237, 129, 40, 0.89)",
+ "value": 80
+ },
+ {
+ "color": "rgba(245, 54, 54, 0.9)",
+ "value": 90
+ }
+ ]
+ },
+ "unit": "percent"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 4,
+ "w": 3,
+ "x": 15,
+ "y": 1
+ },
+ "id": 8,
+ "options": {
+ "minVizHeight": 75,
+ "minVizWidth": 75,
+ "orientation": "auto",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showThresholdLabels": false,
+ "showThresholdMarkers": true,
+ "sizing": "auto"
+ },
+ "pluginVersion": "11.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${datasource}"
+ },
+ "editorMode": "code",
+ "exemplar": false,
+ "expr": "100 - ((node_filesystem_avail_bytes{job=\"node-exporter\",mountpoint=\"/\",fstype!=\"rootfs\"} * 100) / node_filesystem_size_bytes{job=\"node-exporter\",mountpoint=\"/\",fstype!=\"rootfs\"})",
+ "format": "time_series",
+ "instant": true,
+ "intervalFactor": 1,
+ "range": false,
+ "refId": "A",
+ "step": 240
+ }
+ ],
+ "title": "Root FS Used",
+ "type": "gauge"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "description": "Total number of CPU cores",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "mappings": [
+ {
+ "options": {
+ "match": "null",
+ "result": {
+ "text": "N/A"
+ }
+ },
+ "type": "special"
+ }
+ ],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 2,
+ "w": 2,
+ "x": 18,
+ "y": 1
+ },
+ "id": 9,
+ "maxDataPoints": 100,
+ "options": {
+ "colorMode": "none",
+ "graphMode": "none",
+ "justifyMode": "auto",
+ "orientation": "horizontal",
+ "percentChangeColorMode": "standard",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
+ },
+ "pluginVersion": "11.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${datasource}"
+ },
+ "editorMode": "code",
+ "exemplar": false,
+ "expr": "count(count(node_cpu_seconds_total{job=\"node-exporter\"}) by (cpu))",
+ "instant": true,
+ "legendFormat": "__auto",
+ "range": false,
+ "refId": "A"
+ }
+ ],
+ "title": "CPU Cores",
+ "type": "stat"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "description": "System uptime",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "decimals": 1,
+ "mappings": [
+ {
+ "options": {
+ "match": "null",
+ "result": {
+ "text": "N/A"
+ }
+ },
+ "type": "special"
+ }
+ ],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 2,
+ "w": 4,
+ "x": 20,
+ "y": 1
+ },
+ "hideTimeOverride": true,
+ "id": 10,
+ "maxDataPoints": 100,
+ "options": {
+ "colorMode": "none",
+ "graphMode": "none",
+ "justifyMode": "auto",
+ "orientation": "horizontal",
+ "percentChangeColorMode": "standard",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
+ },
+ "pluginVersion": "11.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${datasource}"
+ },
+ "editorMode": "code",
+ "exemplar": false,
+ "expr": "node_time_seconds{job=\"node-exporter\"} - node_boot_time_seconds{job=\"node-exporter\"}",
+ "instant": true,
+ "intervalFactor": 1,
+ "range": false,
+ "refId": "A",
+ "step": 240
+ }
+ ],
+ "title": "Uptime",
+ "type": "stat"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "description": "Total RootFS",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "decimals": 0,
+ "mappings": [
+ {
+ "options": {
+ "match": "null",
+ "result": {
+ "text": "N/A"
+ }
+ },
+ "type": "special"
+ }
+ ],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "rgba(50, 172, 45, 0.97)",
+ "value": null
+ },
+ {
+ "color": "rgba(237, 129, 40, 0.89)",
+ "value": 70
+ },
+ {
+ "color": "rgba(245, 54, 54, 0.9)",
+ "value": 90
+ }
+ ]
+ },
+ "unit": "bytes"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 2,
+ "w": 2,
+ "x": 18,
+ "y": 3
+ },
+ "id": 11,
+ "maxDataPoints": 100,
+ "options": {
+ "colorMode": "none",
+ "graphMode": "none",
+ "justifyMode": "auto",
+ "orientation": "horizontal",
+ "percentChangeColorMode": "standard",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
+ },
+ "pluginVersion": "11.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${datasource}"
+ },
+ "editorMode": "code",
+ "exemplar": false,
+ "expr": "node_filesystem_size_bytes{job=\"node-exporter\",mountpoint=\"/\",fstype!=\"rootfs\"}",
+ "format": "time_series",
+ "hide": false,
+ "instant": true,
+ "intervalFactor": 1,
+ "range": false,
+ "refId": "A",
+ "step": 240
+ }
+ ],
+ "title": "RootFS Total",
+ "type": "stat"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "description": "Total RAM",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "decimals": 0,
+ "mappings": [
+ {
+ "options": {
+ "match": "null",
+ "result": {
+ "text": "N/A"
+ }
+ },
+ "type": "special"
+ }
+ ],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "bytes"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 2,
+ "w": 2,
+ "x": 20,
+ "y": 3
+ },
+ "id": 12,
+ "maxDataPoints": 100,
+ "options": {
+ "colorMode": "none",
+ "graphMode": "none",
+ "justifyMode": "auto",
+ "orientation": "horizontal",
+ "percentChangeColorMode": "standard",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
+ },
+ "pluginVersion": "11.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${datasource}"
+ },
+ "editorMode": "code",
+ "exemplar": false,
+ "expr": "node_memory_MemTotal_bytes{job=\"node-exporter\"}",
+ "instant": true,
+ "intervalFactor": 1,
+ "range": false,
+ "refId": "A",
+ "step": 240
+ }
+ ],
+ "title": "RAM Total",
+ "type": "stat"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "description": "Total SWAP",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "decimals": 0,
+ "mappings": [
+ {
+ "options": {
+ "match": "null",
+ "result": {
+ "text": "N/A"
+ }
+ },
+ "type": "special"
+ }
+ ],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "bytes"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 2,
+ "w": 2,
+ "x": 22,
+ "y": 3
+ },
+ "id": 13,
+ "maxDataPoints": 100,
+ "options": {
+ "colorMode": "none",
+ "graphMode": "none",
+ "justifyMode": "auto",
+ "orientation": "horizontal",
+ "percentChangeColorMode": "standard",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
+ },
+ "pluginVersion": "11.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${datasource}"
+ },
+ "editorMode": "code",
+ "exemplar": false,
+ "expr": "node_memory_SwapTotal_bytes{job=\"node-exporter\"}",
+ "instant": true,
+ "intervalFactor": 1,
+ "range": false,
+ "refId": "A",
+ "step": 240
+ }
+ ],
+ "title": "SWAP Total",
+ "type": "stat"
+ },
+ {
+ "collapsed": false,
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 5
+ },
+ "id": 14,
+ "panels": [],
+ "title": "Sandbox CPU / MEM / REQ",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 6
+ },
+ "id": 15,
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "8.0.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"___EXPR_NAMESPACE___\", container!=\"\"}[5m])) by (pod)",
+ "interval": "",
+ "legendFormat": "{{pod}}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "CPU Usage (container)",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 6
+ },
+ "id": 17,
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "8.0.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "rate(process_cpu_seconds_total{namespace=\"___EXPR_NAMESPACE___\"}[5m])",
+ "interval": "",
+ "legendFormat": "{{pod}}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "CPU Usage (process)",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "bytes"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 14
+ },
+ "id": 16,
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "8.0.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "sum(rate(container_memory_usage_bytes{namespace=\"___EXPR_NAMESPACE___\", container!=\"\"}[5m])) by (pod)",
+ "interval": "",
+ "legendFormat": "{{pod}}",
+ "range": true,
+ "refId": "B"
+ }
+ ],
+ "title": "Memory Usage (container)",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 14
+ },
+ "id": 18,
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "8.0.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "rate(process_resident_memory_bytes{namespace=\"___EXPR_NAMESPACE___\"}[5m])",
+ "interval": "",
+ "legendFormat": "{{pod}}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Memory Usage (process)",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 15,
+ "x": 0,
+ "y": 22
+ },
+ "id": 25,
+ "options": {
+ "legend": {
+ "calcs": [
+ "mean",
+ "lastNotNull",
+ "max",
+ "min"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "maxHeight": 600,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.1.5",
+ "targets": [
+ {
+ "$$hashKey": "object:214",
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "disableTextWrap": false,
+ "editorMode": "code",
+ "expr": "sum by(handler) (rate(http_requests_total{namespace=\"___EXPR_NAMESPACE___\", handler!~\"/metrics|/v1/health_check|none\"}[1m]))",
+ "format": "time_series",
+ "fullMetaSearch": false,
+ "includeNullMetadata": true,
+ "interval": "",
+ "intervalFactor": 1,
+ "legendFormat": "{{ method }} {{ handler }}",
+ "range": true,
+ "refId": "A",
+ "useBackend": false
+ }
+ ],
+ "title": "Total requests per second",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "bars",
+ "fillOpacity": 100,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "normal"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "4xx"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "red",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "HTTP 500"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "#bf1b00",
+ "mode": "fixed"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 9,
+ "x": 15,
+ "y": 22
+ },
+ "id": 26,
+ "options": {
+ "legend": {
+ "calcs": [
+ "mean",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "maxHeight": 600,
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.1.5",
+ "targets": [
+ {
+ "$$hashKey": "object:140",
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "disableTextWrap": false,
+ "editorMode": "code",
+ "expr": "sum by(status) (rate(http_requests_total{namespace=\"___EXPR_NAMESPACE___\"}[1m]))",
+ "format": "time_series",
+ "fullMetaSearch": false,
+ "includeNullMetadata": true,
"interval": "",
- "legendFormat": "{{pod}}",
+ "intervalFactor": 1,
+ "legendFormat": "{{ status }}",
"range": true,
- "refId": "A"
+ "refId": "A",
+ "useBackend": false
+ }
+ ],
+ "title": "Request per second",
+ "type": "timeseries"
+ },
+ {
+ "collapsed": true,
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 30
+ },
+ "id": 19,
+ "panels": [
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "fieldMinMax": false,
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 1000
+ }
+ ]
+ },
+ "unit": "ms"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 0,
+ "y": 31
+ },
+ "id": 20,
+ "options": {
+ "colorMode": "value",
+ "graphMode": "area",
+ "justifyMode": "auto",
+ "orientation": "auto",
+ "percentChangeColorMode": "standard",
+ "reduceOptions": {
+ "calcs": [
+ "mean"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
+ },
+ "pluginVersion": "11.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "(histogram_quantile(0.5, sum by (le) (rate(tgi_request_queue_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m]))) * 1000) > 0",
+ "hide": true,
+ "instant": false,
+ "legendFormat": "__auto",
+ "range": true,
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "(histogram_quantile(0.5, sum by (le) (rate(tgi_batch_inference_duration_bucket{method=\"prefill\", namespace=\"___EXPR_NAMESPACE___\"}[10m]))) * 1000) > 0",
+ "hide": true,
+ "instant": false,
+ "legendFormat": "__auto",
+ "range": true,
+ "refId": "C"
+ },
+ {
+ "datasource": {
+ "name": "Expression",
+ "type": "__expr__",
+ "uid": "__expr__"
+ },
+ "expression": "$B + $C",
+ "hide": false,
+ "refId": "D",
+ "type": "math"
+ }
+ ],
+ "title": "Time to first token",
+ "type": "stat"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "ms"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 8,
+ "y": 31
+ },
+ "id": 21,
+ "options": {
+ "colorMode": "value",
+ "graphMode": "area",
+ "justifyMode": "auto",
+ "orientation": "auto",
+ "percentChangeColorMode": "standard",
+ "reduceOptions": {
+ "calcs": [
+ "mean"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
+ },
+ "pluginVersion": "11.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "(histogram_quantile(0.5, sum by (le) (rate(tgi_batch_forward_duration_bucket{method=\"decode\", namespace=\"___EXPR_NAMESPACE___\"}[10m]))) * 1000)>0",
+ "instant": false,
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Decode per-token latency",
+ "type": "stat"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 16,
+ "y": 31
+ },
+ "id": 22,
+ "options": {
+ "colorMode": "value",
+ "graphMode": "area",
+ "justifyMode": "auto",
+ "orientation": "auto",
+ "percentChangeColorMode": "standard",
+ "reduceOptions": {
+ "calcs": [
+ "mean"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
+ },
+ "pluginVersion": "11.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "sum((rate(tgi_request_generated_tokens_sum{namespace=\"___EXPR_NAMESPACE___\"}[10m]) / rate(tgi_request_generated_tokens_count{namespace=\"___EXPR_NAMESPACE___\"}[10m]))>0)",
+ "instant": false,
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Throughput (generated tok/s)",
+ "type": "stat"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "none"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p50"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "green",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p90"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "orange",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p99"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "red",
+ "mode": "fixed"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 38
+ },
+ "id": 23,
+ "options": {
+ "legend": {
+ "calcs": [
+ "min",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "maxHeight": 600,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.5, sum by (le) (rate(tgi_request_input_length_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "legendFormat": "p50",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.9, sum by (le) (rate(tgi_request_input_length_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "hide": false,
+ "legendFormat": "p90",
+ "range": true,
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.99, sum by (le) (rate(tgi_request_input_length_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "hide": false,
+ "legendFormat": "p99",
+ "range": true,
+ "refId": "C"
+ }
+ ],
+ "title": "Number of tokens per prompt",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "none"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p50"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "green",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p90"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "orange",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p99"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "red",
+ "mode": "fixed"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 38
+ },
+ "id": 24,
+ "options": {
+ "legend": {
+ "calcs": [
+ "min",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "maxHeight": 600,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.5, sum by (le) (rate(tgi_request_generated_tokens_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "legendFormat": "p50",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.9, sum by (le) (rate(tgi_request_generated_tokens_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "hide": false,
+ "legendFormat": "p90",
+ "range": true,
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.99, sum by (le) (rate(tgi_request_generated_tokens_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "hide": false,
+ "legendFormat": "p99",
+ "range": true,
+ "refId": "C"
+ }
+ ],
+ "title": "Number of generated tokens per request",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 30,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 6,
+ "x": 0,
+ "y": 46
+ },
+ "id": 27,
+ "maxDataPoints": 100,
+ "options": {
+ "legend": {
+ "calcs": [
+ "min",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "maxHeight": 600,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "sum(increase(tgi_request_success{namespace=\"___EXPR_NAMESPACE___\"}[1m]))",
+ "legendFormat": "Success",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "sum(increase(tgi_request_failure{namespace=\"___EXPR_NAMESPACE___\"}[1m])) by (err)",
+ "hide": false,
+ "legendFormat": "Error: {{err}}",
+ "range": true,
+ "refId": "B"
+ }
+ ],
+ "title": "Requests",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p50"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "green",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p90"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "orange",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p99"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "red",
+ "mode": "fixed"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 13,
+ "w": 9,
+ "x": 6,
+ "y": 46
+ },
+ "id": 30,
+ "options": {
+ "legend": {
+ "calcs": [
+ "min",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "maxHeight": 600,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.5, sum by (le) (rate(tgi_request_mean_time_per_token_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "legendFormat": "p50",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.9, sum by (le) (rate(tgi_request_mean_time_per_token_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "hide": false,
+ "legendFormat": "p90",
+ "range": true,
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.99, sum by (le) (rate(tgi_request_mean_time_per_token_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "hide": false,
+ "legendFormat": "p99",
+ "range": true,
+ "refId": "C"
+ }
+ ],
+ "title": "Mean Time Per Token quantiles",
+ "type": "timeseries"
+ },
+ {
+ "cards": {},
+ "color": {
+ "cardColor": "#5794F2",
+ "colorScale": "linear",
+ "colorScheme": "interpolateSpectral",
+ "exponent": 0.5,
+ "min": 0,
+ "mode": "opacity"
+ },
+ "dataFormat": "tsbuckets",
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "custom": {
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "scaleDistribution": {
+ "type": "linear"
+ }
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 13,
+ "w": 9,
+ "x": 15,
+ "y": 46
+ },
+ "heatmap": {},
+ "hideZeroBuckets": false,
+ "highlightCards": true,
+ "id": 31,
+ "legend": {
+ "show": false
+ },
+ "maxDataPoints": 25,
+ "options": {
+ "calculate": false,
+ "calculation": {},
+ "cellGap": 2,
+ "cellValues": {},
+ "color": {
+ "exponent": 0.5,
+ "fill": "#5794F2",
+ "min": 0,
+ "mode": "scheme",
+ "reverse": false,
+ "scale": "exponential",
+ "scheme": "Spectral",
+ "steps": 128
+ },
+ "exemplars": {
+ "color": "rgba(255,0,255,0.7)"
+ },
+ "filterValues": {
+ "le": 1e-9
+ },
+ "legend": {
+ "show": false
+ },
+ "rowsFrame": {
+ "layout": "auto"
+ },
+ "showValue": "never",
+ "tooltip": {
+ "maxHeight": 600,
+ "mode": "single",
+ "showColorScale": false,
+ "yHistogram": false
+ },
+ "yAxis": {
+ "axisPlacement": "left",
+ "decimals": 1,
+ "reverse": false,
+ "unit": "s"
+ }
+ },
+ "pluginVersion": "11.2.0",
+ "reverseYBuckets": false,
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "exemplar": true,
+ "expr": "sum(increase(tgi_request_mean_time_per_token_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[5m])) by (le)",
+ "format": "heatmap",
+ "interval": "",
+ "legendFormat": "{{ le }}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Mean Time Per Token",
+ "tooltip": {
+ "show": true,
+ "showHistogram": false
+ },
+ "type": "heatmap",
+ "xAxis": {
+ "show": true
+ },
+ "yAxis": {
+ "decimals": 1,
+ "format": "s",
+ "logBase": 1,
+ "show": true
+ },
+ "yBucketBound": "auto"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "percentage",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "orange",
+ "value": 70
+ },
+ {
+ "color": "red",
+ "value": 85
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 5,
+ "w": 3,
+ "x": 0,
+ "y": 54
+ },
+ "id": 28,
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": false
+ },
+ "tooltip": {
+ "maxHeight": 600,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "9.1.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "count(tgi_request_count{namespace=\"___EXPR_NAMESPACE___\"})",
+ "legendFormat": "Replicas",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Number of replicas",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "mappings": [],
+ "thresholds": {
+ "mode": "percentage",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "orange",
+ "value": 70
+ },
+ {
+ "color": "red",
+ "value": 85
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 5,
+ "w": 3,
+ "x": 3,
+ "y": 54
+ },
+ "id": 29,
+ "options": {
+ "minVizHeight": 75,
+ "minVizWidth": 75,
+ "orientation": "auto",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showThresholdLabels": false,
+ "showThresholdMarkers": true,
+ "sizing": "auto"
+ },
+ "pluginVersion": "11.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "sum(tgi_queue_size{namespace=\"___EXPR_NAMESPACE___\"})",
+ "legendFormat": "__auto",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Queue Size",
+ "type": "gauge"
}
],
- "title": "Memory Usage (process)",
- "type": "timeseries"
+ "title": "Sandbox TGI",
+ "type": "row"
+ },
+ {
+ "collapsed": true,
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 31
+ },
+ "id": 32,
+ "panels": [
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 30,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 6,
+ "x": 0,
+ "y": 60
+ },
+ "id": 33,
+ "maxDataPoints": 100,
+ "options": {
+ "legend": {
+ "calcs": [
+ "min",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "maxHeight": 600,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "sum(increase(te_embed_success{namespace=\"___EXPR_NAMESPACE___\"}[1m]))",
+ "legendFormat": "Success",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "sum(increase(te_embed_count{namespace=\"___EXPR_NAMESPACE___\"}[1m]))",
+ "hide": false,
+ "legendFormat": "Total Count",
+ "range": true,
+ "refId": "B"
+ }
+ ],
+ "title": "Requests",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p50"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "green",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p90"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "orange",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p99"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "red",
+ "mode": "fixed"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 13,
+ "w": 9,
+ "x": 6,
+ "y": 60
+ },
+ "id": 36,
+ "options": {
+ "legend": {
+ "calcs": [
+ "min",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "maxHeight": 600,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.5, sum by (le) (rate(te_embed_queue_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "legendFormat": "p50",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.9, sum by (le) (rate(te_embed_queue_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "hide": false,
+ "legendFormat": "p90",
+ "range": true,
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.99, sum by (le) (rate(te_embed_queue_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "hide": false,
+ "legendFormat": "p99",
+ "range": true,
+ "refId": "C"
+ }
+ ],
+ "title": "Queue Duration quantiles",
+ "type": "timeseries"
+ },
+ {
+ "cards": {},
+ "color": {
+ "cardColor": "#5794F2",
+ "colorScale": "linear",
+ "colorScheme": "interpolateSpectral",
+ "exponent": 0.5,
+ "min": 0,
+ "mode": "opacity"
+ },
+ "dataFormat": "tsbuckets",
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "custom": {
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "scaleDistribution": {
+ "type": "linear"
+ }
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 13,
+ "w": 9,
+ "x": 15,
+ "y": 60
+ },
+ "heatmap": {},
+ "hideZeroBuckets": false,
+ "highlightCards": true,
+ "id": 37,
+ "legend": {
+ "show": false
+ },
+ "maxDataPoints": 25,
+ "options": {
+ "calculate": false,
+ "calculation": {},
+ "cellGap": 2,
+ "cellValues": {},
+ "color": {
+ "exponent": 0.5,
+ "fill": "#5794F2",
+ "min": 0,
+ "mode": "scheme",
+ "reverse": false,
+ "scale": "exponential",
+ "scheme": "Spectral",
+ "steps": 128
+ },
+ "exemplars": {
+ "color": "rgba(255,0,255,0.7)"
+ },
+ "filterValues": {
+ "le": 1e-9
+ },
+ "legend": {
+ "show": false
+ },
+ "rowsFrame": {
+ "layout": "auto"
+ },
+ "showValue": "never",
+ "tooltip": {
+ "maxHeight": 600,
+ "mode": "single",
+ "showColorScale": false,
+ "yHistogram": false
+ },
+ "yAxis": {
+ "axisPlacement": "left",
+ "decimals": 1,
+ "reverse": false,
+ "unit": "s"
+ }
+ },
+ "pluginVersion": "11.2.0",
+ "reverseYBuckets": false,
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "exemplar": true,
+ "expr": "sum(increase(te_request_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[5m])) by (le)",
+ "format": "heatmap",
+ "interval": "",
+ "legendFormat": "{{ le }}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "E2E Latency",
+ "tooltip": {
+ "show": true,
+ "showHistogram": false
+ },
+ "type": "heatmap",
+ "xAxis": {
+ "show": true
+ },
+ "yAxis": {
+ "decimals": 1,
+ "format": "s",
+ "logBase": 1,
+ "show": true
+ },
+ "yBucketBound": "auto"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "percentage",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "orange",
+ "value": 70
+ },
+ {
+ "color": "red",
+ "value": 85
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 5,
+ "w": 3,
+ "x": 0,
+ "y": 68
+ },
+ "id": 34,
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": false
+ },
+ "tooltip": {
+ "maxHeight": 600,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "9.1.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "count(te_request_count{namespace=\"___EXPR_NAMESPACE___\"})",
+ "legendFormat": "Replicas",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Number of replicas",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "mappings": [],
+ "thresholds": {
+ "mode": "percentage",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "orange",
+ "value": 70
+ },
+ {
+ "color": "red",
+ "value": 85
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 5,
+ "w": 3,
+ "x": 3,
+ "y": 68
+ },
+ "id": 35,
+ "options": {
+ "minVizHeight": 75,
+ "minVizWidth": 75,
+ "orientation": "auto",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showThresholdLabels": false,
+ "showThresholdMarkers": true,
+ "sizing": "auto"
+ },
+ "pluginVersion": "11.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "sum(te_queue_size{namespace=\"___EXPR_NAMESPACE___\"})",
+ "legendFormat": "__auto",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Queue Size",
+ "type": "gauge"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p50"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "green",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p90"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "orange",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p99"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "red",
+ "mode": "fixed"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 14,
+ "w": 6,
+ "x": 0,
+ "y": 73
+ },
+ "id": 38,
+ "options": {
+ "legend": {
+ "calcs": [
+ "min",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "maxHeight": 600,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.5, sum by (le) (rate(te_embed_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "legendFormat": "p50",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.9, sum by (le) (rate(te_embed_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "hide": false,
+ "legendFormat": "p90",
+ "range": true,
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.99, sum by (le) (rate(te_embed_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "hide": false,
+ "legendFormat": "p99",
+ "range": true,
+ "refId": "C"
+ }
+ ],
+ "title": "Latency quantiles",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p50"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "green",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p90"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "orange",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p99"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "red",
+ "mode": "fixed"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 14,
+ "w": 9,
+ "x": 6,
+ "y": 73
+ },
+ "id": 39,
+ "options": {
+ "legend": {
+ "calcs": [
+ "min",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "maxHeight": 600,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.5, sum by (le) (rate(te_request_tokenization_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "legendFormat": "p50",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.9, sum by (le) (rate(te_request_tokenization_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "hide": false,
+ "legendFormat": "p90",
+ "range": true,
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.99, sum by (le) (rate(te_request_tokenization_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "hide": false,
+ "legendFormat": "p99",
+ "range": true,
+ "refId": "C"
+ }
+ ],
+ "title": "Tokenization Duration quantiles",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p50"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "green",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p90"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "orange",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p99"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "red",
+ "mode": "fixed"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 9,
+ "x": 15,
+ "y": 73
+ },
+ "id": 40,
+ "options": {
+ "legend": {
+ "calcs": [
+ "min",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "maxHeight": 600,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.5, sum by (le) (rate(te_request_inference_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "legendFormat": "p50",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.9, sum by (le) (rate(te_request_inference_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "hide": false,
+ "legendFormat": "p90",
+ "range": true,
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.99, sum by (le) (rate(te_request_inference_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "hide": false,
+ "legendFormat": "p99",
+ "range": true,
+ "refId": "C"
+ }
+ ],
+ "title": "Inference quantiles",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "default": true,
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p50"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "green",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p90"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "orange",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "p99"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "red",
+ "mode": "fixed"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 9,
+ "x": 15,
+ "y": 80
+ },
+ "id": 41,
+ "options": {
+ "legend": {
+ "calcs": [
+ "min",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "maxHeight": 600,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.5, sum by (le) (rate(te_embed_tokenization_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "legendFormat": "p50",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.9, sum by (le) (rate(te_embed_tokenization_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "hide": false,
+ "legendFormat": "p90",
+ "range": true,
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "prometheus"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.99, sum by (le) (rate(te_embed_tokenization_duration_bucket{namespace=\"___EXPR_NAMESPACE___\"}[10m])))",
+ "hide": false,
+ "legendFormat": "p99",
+ "range": true,
+ "refId": "C"
+ }
+ ],
+ "title": "Tokenization Latency quantiles",
+ "type": "timeseries"
+ }
+ ],
+ "title": "Sandbox TEI",
+ "type": "row"
}
],
+ "refresh": "30s",
"schemaVersion": 39,
"tags": [],
"templating": {
@@ -428,38 +4150,11 @@
"from": "now-30m",
"to": "now"
},
- "timepicker": {
- "refresh_intervals": [
- "5s",
- "10s",
- "30s",
- "1m",
- "5m",
- "15m",
- "30m",
- "1h",
- "2h",
- "1d"
- ],
- "time_options": [
- "5m",
- "15m",
- "1h",
- "6h",
- "12h",
- "24h",
- "2d",
- "7d",
- "30d"
- ]
- },
- "timezone": "",
+ "timepicker": {},
+ "timezone": "browser",
"title": "___DASHBOARD_TITLE___",
"uid": "___DASHBOARD_UID___",
- "version": 2,
- "weekStart": "",
- "overwrite": false,
- "folderId": 0,
- "message": "Imported by API"
+ "version": 1,
+ "weekStart": ""
}
}
\ No newline at end of file
diff --git a/studio-frontend/packages/server/.gitignore b/studio-frontend/packages/server/.gitignore
new file mode 100644
index 0000000..b3ab1ae
--- /dev/null
+++ b/studio-frontend/packages/server/.gitignore
@@ -0,0 +1,6 @@
+.idea/
+.vscode/
+node_modules/
+build/
+tmp/
+temp/
\ No newline at end of file
diff --git a/studio-frontend/packages/server/bin/run b/studio-frontend/packages/server/bin/run
old mode 100644
new mode 100755
diff --git a/studio-frontend/packages/server/src/DataSource.ts b/studio-frontend/packages/server/src/DataSource.ts
index 811f62b..5ac39bc 100644
--- a/studio-frontend/packages/server/src/DataSource.ts
+++ b/studio-frontend/packages/server/src/DataSource.ts
@@ -78,6 +78,7 @@ export const init = async (): Promise => {
break
default:
homePath = process.env.DATABASE_PATH ?? flowisePath
+ console.log ("***", path.resolve(homePath, 'database.sqlite'))
appDataSource = new DataSource({
type: 'sqlite',
database: path.resolve(homePath, 'database.sqlite'),
@@ -104,7 +105,18 @@ const getDatabaseSSLFromEnv = () => {
ca: Buffer.from(process.env.DATABASE_SSL_KEY_BASE64, 'base64')
}
} else if (process.env.DATABASE_SSL === 'true') {
- return true
+ // return true
+ try {
+ return {
+ rejectUnauthorized: false,
+ ca: fs.readFileSync('/etc/mysql/ssl/ca.pem'),
+ cert: fs.readFileSync('/etc/mysql/ssl/client-cert.pem'),
+ key: fs.readFileSync('/etc/mysql/ssl/client-key.pem')
+ };
+ } catch (error) {
+ console.error('Error reading certificates from mounted path:', error);
+ return undefined;
+ }
}
return undefined
}
diff --git a/studio-frontend/packages/server/src/Interface.ts b/studio-frontend/packages/server/src/Interface.ts
index 2da6787..228ddc3 100644
--- a/studio-frontend/packages/server/src/Interface.ts
+++ b/studio-frontend/packages/server/src/Interface.ts
@@ -21,6 +21,7 @@ export enum ChatMessageRatingType {
export interface IChatFlow {
id: string
name: string
+ userid: string
flowData: string
updatedDate: Date
createdDate: Date
diff --git a/studio-frontend/packages/server/src/controllers/chatflows/index.ts b/studio-frontend/packages/server/src/controllers/chatflows/index.ts
index 3c91449..c09cfd3 100644
--- a/studio-frontend/packages/server/src/controllers/chatflows/index.ts
+++ b/studio-frontend/packages/server/src/controllers/chatflows/index.ts
@@ -58,6 +58,15 @@ const getAllChatflows = async (req: Request, res: Response, next: NextFunction)
}
}
+const getAllChatflowsbyUserId = async (req: Request, res: Response, next: NextFunction) => {
+ try {
+ const apiResponse = await chatflowsService.getAllChatflowsbyUserId(req.query.userid as string, req.query.type as ChatflowType)
+ return res.json(apiResponse)
+ } catch (error) {
+ next(error)
+ }
+}
+
// Get specific chatflow via api key
const getChatflowByApiKey = async (req: Request, res: Response, next: NextFunction) => {
try {
@@ -98,6 +107,7 @@ const saveChatflow = async (req: Request, res: Response, next: NextFunction) =>
const body = req.body
const newChatFlow = new ChatFlow()
Object.assign(newChatFlow, body)
+ console.log ('newChatFlow', newChatFlow)
const apiResponse = await chatflowsService.saveChatflow(newChatFlow)
return res.json(apiResponse)
} catch (error) {
@@ -257,6 +267,7 @@ export default {
checkIfChatflowIsValidForUploads,
deleteChatflow,
getAllChatflows,
+ getAllChatflowsbyUserId,
getChatflowByApiKey,
getChatflowById,
saveChatflow,
diff --git a/studio-frontend/packages/server/src/database/entities/ChatFlow.ts b/studio-frontend/packages/server/src/database/entities/ChatFlow.ts
index f86caf2..122d097 100644
--- a/studio-frontend/packages/server/src/database/entities/ChatFlow.ts
+++ b/studio-frontend/packages/server/src/database/entities/ChatFlow.ts
@@ -10,6 +10,9 @@ export class ChatFlow implements IChatFlow {
@Column()
name: string
+ @Column({ nullable: true, type: 'text' })
+ userid: string
+
@Column({ type: 'text' })
flowData: string
diff --git a/studio-frontend/packages/server/src/database/migrations/mysql/1693840429259-Init.ts b/studio-frontend/packages/server/src/database/migrations/mysql/1693840429259-Init.ts
index 9d07206..4e7e8f8 100644
--- a/studio-frontend/packages/server/src/database/migrations/mysql/1693840429259-Init.ts
+++ b/studio-frontend/packages/server/src/database/migrations/mysql/1693840429259-Init.ts
@@ -6,11 +6,15 @@ export class Init1693840429259 implements MigrationInterface {
`CREATE TABLE IF NOT EXISTS \`chat_flow\` (
\`id\` varchar(36) NOT NULL,
\`name\` varchar(255) NOT NULL,
+ \`userid\` varchar(255) DEFAULT NULL,
\`flowData\` text NOT NULL,
\`deployed\` tinyint DEFAULT NULL,
\`isPublic\` tinyint DEFAULT NULL,
\`apikeyid\` varchar(255) DEFAULT NULL,
\`chatbotConfig\` varchar(255) DEFAULT NULL,
+ \`sandboxStatus\` varchar(255) DEFAULT NULL,
+ \`sandboxAppUrl\` varchar(255) DEFAULT NULL,
+ \`sandboxGrafanaUrl\` varchar(255) DEFAULT NULL,
\`createdDate\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
\`updatedDate\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (\`id\`)
diff --git a/studio-frontend/packages/server/src/database/migrations/sqlite/1732778337650-OPEAAddUserIdtoChatFlow.ts b/studio-frontend/packages/server/src/database/migrations/sqlite/1732778337650-OPEAAddUserIdtoChatFlow.ts
new file mode 100644
index 0000000..b802061
--- /dev/null
+++ b/studio-frontend/packages/server/src/database/migrations/sqlite/1732778337650-OPEAAddUserIdtoChatFlow.ts
@@ -0,0 +1,20 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class OPEAAddUserIdtoChatFlow1732778337650 implements MigrationInterface {
+ name = 'OPEAAddUserIdtoChatFlow1732778337650'
+
+ public async up(queryRunner: QueryRunner): Promise {
+ await queryRunner.query(`CREATE TABLE "temporary_chat_flow" ("id" varchar PRIMARY KEY NOT NULL, "name" varchar NOT NULL, "flowData" text NOT NULL, "deployed" boolean, "isPublic" boolean, "apikeyid" varchar, "chatbotConfig" text, "createdDate" datetime NOT NULL DEFAULT (datetime('now')), "updatedDate" datetime NOT NULL DEFAULT (datetime('now')), "sandboxStatus" text, "sandboxAppUrl" text, "sandboxGrafanaUrl" text, "apiConfig" text, "analytic" text, "category" text, "speechToText" text, "type" text, "userid" text)`);
+ await queryRunner.query(`INSERT INTO "temporary_chat_flow"("id", "name", "flowData", "deployed", "isPublic", "apikeyid", "chatbotConfig", "createdDate", "updatedDate", "sandboxStatus", "sandboxAppUrl", "sandboxGrafanaUrl", "apiConfig", "analytic", "category", "speechToText", "type", "userid") SELECT "id", "name", "flowData", "deployed", "isPublic", "apikeyid", "chatbotConfig", "createdDate", "updatedDate", "sandboxStatus", "sandboxAppUrl", "sandboxGrafanaUrl", "apiConfig", "analytic", "category", "speechToText", "type", "userid" FROM "chat_flow"`);
+ await queryRunner.query(`DROP TABLE "chat_flow"`);
+ await queryRunner.query(`ALTER TABLE "temporary_chat_flow" RENAME TO "chat_flow"`);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise {
+ await queryRunner.query(`ALTER TABLE "chat_flow" RENAME TO "temporary_chat_flow"`);
+ await queryRunner.query(`CREATE TABLE "chat_flow" ("id" varchar PRIMARY KEY NOT NULL, "name" varchar NOT NULL, "flowData" text NOT NULL, "deployed" text, "isPublic" boolean, "apikeyid" varchar, "chatbotConfig" text, "createdDate" datetime NOT NULL DEFAULT (datetime('now')), "updatedDate" datetime NOT NULL DEFAULT (datetime('now')), "sandboxStatus" text, "sandboxAppUrl" text, "sandboxGrafanaUrl" text, "apiConfig" text, "analytic" text, "category" text, "speechToText" text, "type" text, "userid" varchar NOT NULL)`);
+ await queryRunner.query(`INSERT INTO "chat_flow"("id", "name", "flowData", "deployed", "isPublic", "apikeyid", "chatbotConfig", "createdDate", "updatedDate", "sandboxStatus", "sandboxAppUrl", "sandboxGrafanaUrl", "apiConfig", "analytic", "category", "speechToText", "type", "userid") SELECT "id", "name", "flowData", "deployed", "isPublic", "apikeyid", "chatbotConfig", "createdDate", "updatedDate", "sandboxStatus", "sandboxAppUrl", "sandboxGrafanaUrl", "apiConfig", "analytic", "category", "speechToText", "type", "userid" FROM "temporary_chat_flow"`);
+ await queryRunner.query(`DROP TABLE "temporary_chat_flow"`);
+ }
+
+}
diff --git a/studio-frontend/packages/server/src/database/migrations/sqlite/index.ts b/studio-frontend/packages/server/src/database/migrations/sqlite/index.ts
index 207dc0c..67401e6 100644
--- a/studio-frontend/packages/server/src/database/migrations/sqlite/index.ts
+++ b/studio-frontend/packages/server/src/database/migrations/sqlite/index.ts
@@ -26,6 +26,8 @@ import { AddActionToChatMessage1721078251523 } from './1721078251523-AddActionTo
import { AddArtifactsToChatMessage1726156258465 } from './1726156258465-AddArtifactsToChatMessage'
import { AddCustomTemplate1725629836652 } from './1725629836652-AddCustomTemplate'
import { OPEAAddSandboxStatustoChatFlow1727419719000 } from './1727419719000-OPEAAddSandboxStatustoChatFlow'
+import { OPEAAddUserIdtoChatFlow1732778337650 } from './1732778337650-OPEAAddUserIdtoChatFlow'
+
export const sqliteMigrations = [
Init1693835579790,
ModifyChatFlow1693920824108,
@@ -54,5 +56,6 @@ export const sqliteMigrations = [
AddActionToChatMessage1721078251523,
AddArtifactsToChatMessage1726156258465,
AddCustomTemplate1725629836652,
- OPEAAddSandboxStatustoChatFlow1727419719000
+ OPEAAddSandboxStatustoChatFlow1727419719000,
+ OPEAAddUserIdtoChatFlow1732778337650,
]
diff --git a/studio-frontend/packages/server/src/routes/chatflows/index.ts b/studio-frontend/packages/server/src/routes/chatflows/index.ts
index b0c5350..ab79258 100644
--- a/studio-frontend/packages/server/src/routes/chatflows/index.ts
+++ b/studio-frontend/packages/server/src/routes/chatflows/index.ts
@@ -7,7 +7,7 @@ router.post('/', chatflowsController.saveChatflow)
router.post('/importchatflows', chatflowsController.importChatflows)
// READ
-router.get('/', chatflowsController.getAllChatflows)
+router.get('/', chatflowsController.getAllChatflowsbyUserId)
router.get(['/', '/:id'], chatflowsController.getChatflowById)
router.get(['/apikey/', '/apikey/:apikey'], chatflowsController.getChatflowByApiKey)
diff --git a/studio-frontend/packages/server/src/services/chatflows/index.ts b/studio-frontend/packages/server/src/services/chatflows/index.ts
index 00b674c..d6b9337 100644
--- a/studio-frontend/packages/server/src/services/chatflows/index.ts
+++ b/studio-frontend/packages/server/src/services/chatflows/index.ts
@@ -134,6 +134,66 @@ const getAllChatflows = async (type?: ChatflowType): Promise => {
}
}
+const getAllChatflowsbyUserId = async (userid: string, type?: ChatflowType): Promise => {
+ try {
+ const appServer = getRunningExpressApp()
+
+ // Use find with a where condition to filter by userid
+ let dbResponse = await appServer.AppDataSource.getRepository(ChatFlow).find({
+ where: {
+ userid: userid, // Filter by the specific userid
+ },
+ })
+
+ // If no chatflows are found for the user, create a new one based from sample workflow
+ if (dbResponse.length === 0) {
+ // URL to fetch the sample workflow
+ const url = 'https://raw.githubusercontent.com/opea-project/GenAIStudio/refs/heads/main/sample-workflows/sample_workflow_chatqna.json';
+
+ try {
+ // Fetch and parse the JSON data from the URL
+ const response = await axios.get(url);
+ const parsedFlowData = response.data;
+
+ // Create a new chatflow with the flowData from the URL
+ const newChatflow: Partial = {
+ userid: userid,
+ name: 'sample-chatqna',
+ flowData: JSON.stringify(parsedFlowData),
+ type: 'OPEA',
+ deployed: false,
+ isPublic: false
+ };
+
+ // Call the importChatflows function to insert the new chatflow
+ await importChatflows([newChatflow]);
+ } catch (error) {
+ throw new Error('Failed to import sample chatflow');
+ }
+
+ // Rerun the find query to fetch the latest state of chatflows after insertion
+ dbResponse = await appServer.AppDataSource.getRepository(ChatFlow).find({
+ where: {
+ userid: userid,
+ },
+ });
+ }
+
+ // Filter further by type if needed
+ if (type) {
+ return dbResponse.filter((chatflow) => chatflow.type === type)
+ }
+
+ return dbResponse
+ } catch (error) {
+ throw new InternalFlowiseError(
+ StatusCodes.INTERNAL_SERVER_ERROR,
+ `Error: chatflowsService.getAllChatflows - ${getErrorMessage(error)}`
+ )
+ }
+}
+
+
const getChatflowByApiKey = async (apiKeyId: string, keyonly?: unknown): Promise => {
try {
// Here we only get chatflows that are bounded by the apikeyid and chatflows that are not bounded by any apikey
@@ -455,6 +515,7 @@ export default {
checkIfChatflowIsValidForUploads,
deleteChatflow,
getAllChatflows,
+ getAllChatflowsbyUserId,
getChatflowByApiKey,
getChatflowById,
saveChatflow,
diff --git a/studio-frontend/packages/ui/package.json b/studio-frontend/packages/ui/package.json
index d8ed6fc..55a60ef 100644
--- a/studio-frontend/packages/ui/package.json
+++ b/studio-frontend/packages/ui/package.json
@@ -20,6 +20,7 @@
"@mui/lab": "5.0.0-alpha.156",
"@mui/material": "5.15.0",
"@mui/x-data-grid": "6.8.0",
+ "@react-keycloak/web": "^3.4.0",
"@tabler/icons-react": "^3.3.0",
"@uiw/codemirror-theme-sublime": "^4.21.21",
"@uiw/codemirror-theme-vscode": "^4.21.21",
@@ -34,6 +35,7 @@
"framer-motion": "^4.1.13",
"history": "^5.0.0",
"html-react-parser": "^3.0.4",
+ "keycloak-js": "^26.0.5",
"lodash": "^4.17.21",
"moment": "^2.29.3",
"notistack": "^2.0.4",
diff --git a/studio-frontend/packages/ui/src/App.jsx b/studio-frontend/packages/ui/src/App.jsx
index 857d4ea..f547d3b 100644
--- a/studio-frontend/packages/ui/src/App.jsx
+++ b/studio-frontend/packages/ui/src/App.jsx
@@ -1,32 +1,26 @@
-import { useSelector } from 'react-redux'
-
-import { ThemeProvider } from '@mui/material/styles'
-import { CssBaseline, StyledEngineProvider } from '@mui/material'
-
-// routing
-import Routes from '@/routes'
-
-// defaultTheme
-import themes from '@/themes'
-
-// project imports
-import NavigationScroll from '@/layout/NavigationScroll'
-
-// ==============================|| APP ||============================== //
+import { useSelector } from 'react-redux';
+import { ThemeProvider } from '@mui/material/styles';
+import { CssBaseline, StyledEngineProvider } from '@mui/material';
+import Routes from '@/routes';
+import themes from '@/themes';
+import NavigationScroll from '@/layout/NavigationScroll';
+import KeycloakProvider from './KeycloakContext'; // Import the updated KeycloakProvider
const App = () => {
- const customization = useSelector((state) => state.customization)
+ const customization = useSelector((state) => state.customization);
return (
-
-
-
-
-
-
+
+
+
+
+
+
+
+
- )
-}
+ );
+};
-export default App
+export default App;
diff --git a/studio-frontend/packages/ui/src/KeycloakContext.jsx b/studio-frontend/packages/ui/src/KeycloakContext.jsx
new file mode 100644
index 0000000..9753ee6
--- /dev/null
+++ b/studio-frontend/packages/ui/src/KeycloakContext.jsx
@@ -0,0 +1,72 @@
+import React, { createContext, useContext, useEffect, useState } from 'react';
+import Keycloak from 'keycloak-js';
+
+// Create the Keycloak context
+const KeycloakContext = createContext(null);
+
+// Provide the Keycloak context to the application
+export const KeycloakProvider = ({ children }) => {
+ const [keycloak, setKeycloak] = useState(null);
+ const [isInitialized, setIsInitialized] = useState(false);
+
+ useEffect(() => {
+ if (!window.crypto || !window.crypto.subtle) {
+ console.error("Web Crypto API is not available. This may cause security issues.");
+ }
+
+ const initOptions = {
+ url: '/auth/',
+ realm: 'genaistudio',
+ clientId: 'genaistudio',
+ onLoad: 'login-required', // check-sso | login-required
+ responseType: 'code', // Corrected from KeycloakResponseType to responseType
+ silentCheckSsoRedirectUri: window.location.origin + "/silent-check-sso.html",
+ checkLoginIframe: false,
+ };
+
+ const kc = new Keycloak(initOptions);
+
+ kc.init({
+ onLoad: initOptions.onLoad,
+ responseType: 'code', // Corrected from KeycloakResponseType to responseType
+ }).then((auth) => {
+ if (!auth) {
+ window.location.reload();
+ } else {
+ console.info("Authenticated");
+ console.log('auth', auth);
+ console.log('Keycloak', kc);
+
+ kc.onTokenExpired = () => {
+ console.log('token expired');
+ };
+
+ setKeycloak(kc); // Set the Keycloak instance in state
+ setIsInitialized(true); // Mark initialization as complete
+ }
+ }).catch((error) => {
+ console.error("Authentication Failed", error);
+ });
+ }, []);
+
+ if (!isInitialized) {
+ return Loading...
; // Show a loading state until Keycloak is initialized
+ }
+
+ return (
+
+ {children}
+
+ );
+};
+
+// Custom hook to use Keycloak context
+export const useKeycloak = () => {
+ const context = useContext(KeycloakContext);
+ if (!context) {
+ throw new Error('useKeycloak must be used within a KeycloakProvider');
+ }
+ return context;
+};
+
+export default KeycloakProvider;
\ No newline at end of file
diff --git a/studio-frontend/packages/ui/src/api/chatflows.js b/studio-frontend/packages/ui/src/api/chatflows.js
index 25ab861..a51798c 100644
--- a/studio-frontend/packages/ui/src/api/chatflows.js
+++ b/studio-frontend/packages/ui/src/api/chatflows.js
@@ -7,6 +7,8 @@ const getAllAgentflows = () => client.get('/chatflows?type=MULTIAGENT')
const getAllOpeaflows = () => client.get('/chatflows?type=OPEA')
+const getUserOpeaflows = (userid) => client.get(`/chatflows?userid=${userid}&type=OPEA`)
+
const getSpecificChatflow = (id) => client.get(`/chatflows/${id}`)
const getSpecificChatflowFromPublicEndpoint = (id) => client.get(`/public-chatflows/${id}`)
@@ -33,6 +35,7 @@ export default {
getAllChatflows,
getAllAgentflows,
getAllOpeaflows,
+ getUserOpeaflows,
getSpecificChatflow,
getSpecificChatflowFromPublicEndpoint,
createNewChatflow,
diff --git a/studio-frontend/packages/ui/src/layout/MainLayout/Header/index.jsx b/studio-frontend/packages/ui/src/layout/MainLayout/Header/index.jsx
index 5d4fba2..8a28478 100644
--- a/studio-frontend/packages/ui/src/layout/MainLayout/Header/index.jsx
+++ b/studio-frontend/packages/ui/src/layout/MainLayout/Header/index.jsx
@@ -18,6 +18,26 @@ import { IconMenu2 } from '@tabler/icons-react'
// store
import { SET_DARKMODE } from '@/store/actions'
+// keycloak context
+import LogoutIcon from '@mui/icons-material/Logout';
+import { useKeycloak } from '../../../KeycloakContext'
+
+const LogoutButton = () => {
+ const keycloak = useKeycloak(); // Access the Keycloak instance
+
+ const handleLogout = () => {
+ keycloak.logout({
+ redirectUri: window.location.origin, // Redirect to the home page or desired URL after logout
+ });
+ };
+
+ return (
+
+
+
+ );
+};
+
// ==============================|| MAIN NAVBAR / HEADER ||============================== //
const MaterialUISwitch = styled(Switch)(({ theme }) => ({
@@ -92,45 +112,43 @@ const Header = ({ handleLeftDrawerToggle }) => {
return (
<>
- {/* logo & toggler button */}
+ {/* Container for logo and logout button */}
-
-
+ {/* Logo Section */}
+
+
+
+
+
+
+ {/* Logout Button */}
+
+
- {/*
-
-
-
- */}
-
- {/* */}
-
- {/* */}
>
+
)
}
diff --git a/studio-frontend/packages/ui/src/layout/MainLayout/index.jsx b/studio-frontend/packages/ui/src/layout/MainLayout/index.jsx
index 5f9acea..83ae6f2 100644
--- a/studio-frontend/packages/ui/src/layout/MainLayout/index.jsx
+++ b/studio-frontend/packages/ui/src/layout/MainLayout/index.jsx
@@ -12,6 +12,8 @@ import Sidebar from './Sidebar'
import { drawerWidth, headerHeight } from '@/store/constant'
import { SET_MENU } from '@/store/actions'
+import {useKeycloak } from '../../KeycloakContext.jsx'
+
// styles
const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })(({ theme, open }) => ({
...theme.typography.mainContent,
@@ -57,6 +59,16 @@ const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })(({
// ==============================|| MAIN LAYOUT ||============================== //
const MainLayout = () => {
+ const keycloak = useKeycloak()
+ console.log ("login roles", keycloak?.tokenParsed?.resource_access?.genaistudio?.roles[0])
+ let userRole = keycloak?.tokenParsed?.resource_access?.genaistudio?.roles[0]
+
+ const handleLogout = () => {
+ keycloak.logout({
+ redirectUri: window.location.origin, // Redirect to the home page or desired URL after logout
+ });
+ };
+
const theme = useTheme()
const matchDownMd = useMediaQuery(theme.breakpoints.down('lg'))
@@ -73,45 +85,51 @@ const MainLayout = () => {
}, [matchDownMd])
return (
-
-
- {/* header */}
-
-
-
-
-
-
- {/* drawer */}
- {/* */}
-
- {/* main content */}
-
-
-
+
+ {/* header */}
+
-
- FlowiseAI
-
-
-
+
+
+
+
-
+ {/* drawer */}
+ {/* */}
+
+ {/* main content */}
+ (
+
+
+
+ FlowiseAI
+
+
+ )
+ ):
+ (
+
+ You are unauthorised. Please contact your admin for approval.
+
+
+ )
)
}
diff --git a/studio-frontend/packages/ui/src/ui-component/table/FlowListTable.jsx b/studio-frontend/packages/ui/src/ui-component/table/FlowListTable.jsx
index 8ba6d73..107ef78 100644
--- a/studio-frontend/packages/ui/src/ui-component/table/FlowListTable.jsx
+++ b/studio-frontend/packages/ui/src/ui-component/table/FlowListTable.jsx
@@ -61,11 +61,12 @@ const getLocalStorageKeyName = (name, isAgentCanvas) => {
return (isAgentCanvas ? 'agentcanvas' : 'chatflowcanvas') + '_' + name
}
-export const FlowListTable = ({ data, images, isLoading, filterFunction, updateFlowsApi, setError, isAgentCanvas, isOpeaCanvas, stopSandboxApi, updateFlowToServerApi }) => {
+export const FlowListTable = ({ data, images, isLoading, filterFunction, updateFlowsApi, setError, isAgentCanvas, isOpeaCanvas, stopSandboxApi, updateFlowToServerApi, userRole }) => {
// overwrite setError
setError = (error) => {
console.error(error)
}
+ // console.log ("table user", userRole)
const theme = useTheme()
const customization = useSelector((state) => state.customization)
@@ -89,7 +90,7 @@ export const FlowListTable = ({ data, images, isLoading, filterFunction, updateF
const handleSortData = () => {
if (!data) return [];
- console.log('handleSortData', data);
+ // console.log('handleSortData', data);
const sorted = [...data].map((row) => ({
...row,
sandboxStatus: row.sandboxStatus || 'Not Running' // Ensure initial status
@@ -288,6 +289,16 @@ export const FlowListTable = ({ data, images, isLoading, filterFunction, updateF
Last Modified Date
+ {userRole === 'admin' &&
+
+
+ User
+
+ }
@@ -309,6 +320,9 @@ export const FlowListTable = ({ data, images, isLoading, filterFunction, updateF
+
+
+
@@ -326,6 +340,9 @@ export const FlowListTable = ({ data, images, isLoading, filterFunction, updateF
+
+
+
>
) : (
@@ -465,6 +482,8 @@ export const FlowListTable = ({ data, images, isLoading, filterFunction, updateF
{moment(row.updatedDate).format('MMMM Do, YYYY')}
+ {userRole=='admin' && {row.userid}}
+
))}
>
diff --git a/studio-frontend/packages/ui/src/views/canvas/index.jsx b/studio-frontend/packages/ui/src/views/canvas/index.jsx
index cc29da6..6b05709 100644
--- a/studio-frontend/packages/ui/src/views/canvas/index.jsx
+++ b/studio-frontend/packages/ui/src/views/canvas/index.jsx
@@ -55,12 +55,16 @@ import { usePrompt } from '@/utils/usePrompt'
// const
import { FLOWISE_CREDENTIAL_ID } from '@/store/constant'
+// keycloak context
+import { useKeycloak } from '../../KeycloakContext'
+
const nodeTypes = { customNode: CanvasNode, stickyNote: StickyNote }
const edgeTypes = { buttonedge: ButtonEdge }
// ==============================|| CANVAS ||============================== //
const Canvas = () => {
+ const keycloak = useKeycloak()
const theme = useTheme()
const navigate = useNavigate()
@@ -223,12 +227,16 @@ const Canvas = () => {
rfInstanceObject.nodes = nodes
const flowData = JSON.stringify(rfInstanceObject)
+ console.log (chatflowName)
+ console.log (keycloak?.tokenParsed)
+
if (!chatflow.id) {
const newChatflowBody = {
name: chatflowName,
deployed: false,
isPublic: false,
flowData,
+ userid: keycloak?.tokenParsed?.email ? keycloak.tokenParsed.email : '',
type: isAgentCanvas ? 'MULTIAGENT' : isOpeaCanvas ? 'OPEA' : 'CHATFLOW'
}
createNewChatflowApi.request(newChatflowBody)
diff --git a/studio-frontend/packages/ui/src/views/opeaflows/index.jsx b/studio-frontend/packages/ui/src/views/opeaflows/index.jsx
index d2b6423..8286db8 100644
--- a/studio-frontend/packages/ui/src/views/opeaflows/index.jsx
+++ b/studio-frontend/packages/ui/src/views/opeaflows/index.jsx
@@ -29,9 +29,13 @@ import { baseURL } from '@/store/constant'
// icons
import { IconPlus, IconLayoutGrid, IconList } from '@tabler/icons-react'
+//keycloak
+import { useKeycloak } from '../../KeycloakContext'
+
// ==============================|| OPEAFlows ||============================== //
const Opeaflows = () => {
+ const keycloak = useKeycloak()
const navigate = useNavigate()
const theme = useTheme()
@@ -42,7 +46,22 @@ const Opeaflows = () => {
const [loginDialogOpen, setLoginDialogOpen] = useState(false)
const [loginDialogProps, setLoginDialogProps] = useState({})
- const getAllOpeaflowsApi = useApi(chatflowsApi.getAllOpeaflows)
+ console.log ("roles", keycloak?.tokenParsed?.resource_access?.genaistudio?.roles[0])
+ let userRole = keycloak?.tokenParsed?.resource_access?.genaistudio?.roles[0]
+ let getAllOpeaflowsApi = null
+ if (keycloak.authenticated) {
+ getAllOpeaflowsApi = useApi(chatflowsApi.getAllOpeaflows)
+
+ if (userRole === 'admin') {
+ getAllOpeaflowsApi = useApi(chatflowsApi.getAllOpeaflows)
+ }
+ else if (userRole === 'user') {
+ getAllOpeaflowsApi = useApi(() => chatflowsApi.getUserOpeaflows(keycloak.tokenParsed.email));
+ console.log("email", keycloak.tokenParsed.email)
+ console.log ("get user opeaflows", getAllOpeaflowsApi)
+ }
+ }
+
const stopSandboxApi = chatflowsApi.stopSandbox
const updateFlowToServerApi = chatflowsApi.updateChatflow
const [view, setView] = useState(localStorage.getItem('flowDisplayStyle') || 'list')
@@ -86,15 +105,16 @@ const Opeaflows = () => {
useEffect(() => {
if (getAllOpeaflowsApi.error) {
- if (getAllOpeaflowsApi.error?.response?.status === 401) {
- setLoginDialogProps({
- title: 'Login',
- confirmButtonName: 'Login'
- })
- setLoginDialogOpen(true)
- } else {
- setError(getAllOpeaflowsApi.error)
- }
+ console.log ("error", getAllOpeaflowsApi.error)
+ // if (getAllOpeaflowsApi.error?.response?.status === 401) {
+ // setLoginDialogProps({
+ // title: 'Login',
+ // confirmButtonName: 'Login'
+ // })
+ // setLoginDialogOpen(true)
+ // } else {
+ // setError(getAllOpeaflowsApi.error)
+ // }
}
}, [getAllOpeaflowsApi.error])
@@ -196,6 +216,7 @@ const Opeaflows = () => {
setError={setError}
stopSandboxApi={stopSandboxApi}
isOpeaCanvas={true}
+ userRole={userRole}
/>
)}
{!isLoading && (!getAllOpeaflowsApi.data || getAllOpeaflowsApi.data.length === 0) && (
diff --git a/studio-frontend/packages/ui/vite.config.js b/studio-frontend/packages/ui/vite.config.js
index 1d51668..c987920 100644
--- a/studio-frontend/packages/ui/vite.config.js
+++ b/studio-frontend/packages/ui/vite.config.js
@@ -37,8 +37,8 @@ export default defineConfig(async ({ mode }) => {
server: {
open: true,
proxy,
- port: process.env.VITE_PORT ?? 8080,
- host: process.env.VITE_HOST
+ port: process.env.VITE_PORT ?? 8088,
+ host: process.env.VITE_HOST ?? '0.0.0.0'
}
}
})
diff --git a/tests/playwright/studio-e2e/001_test_sandbox_deployment.spec.ts b/tests/playwright/studio-e2e/001_test_sandbox_deployment.spec.ts
index 4815eda..146ba7a 100644
--- a/tests/playwright/studio-e2e/001_test_sandbox_deployment.spec.ts
+++ b/tests/playwright/studio-e2e/001_test_sandbox_deployment.spec.ts
@@ -4,11 +4,18 @@ import fs from 'fs';
import path from 'path';
import os from 'os';
-test('001_test_sandbox_deployment', async ({ page, baseURL }) => {
+test('001_test_sandbox_deployment', async ({ browser, baseURL }) => {
test.setTimeout(600000);
-
+ const context = await browser.newContext({
+ ignoreHTTPSErrors: true
+ });
+ const page = await context.newPage();
const IDC_URL = baseURL || ""
await page.goto(IDC_URL);
+ await page.getByLabel('Username or email').fill('test_automation@gmail.com');
+ await page.getByLabel('Password', { exact: true }).click();
+ await page.getByLabel('Password', { exact: true }).fill('test');
+ await page.getByRole('button', { name: 'Sign In' }).click();
await page.getByRole('button', { name: 'Create New Workflow' }).click();
await page.getByRole('button', { name: 'Settings' }).click();
let fileChooserPromise = page.waitForEvent('filechooser');
diff --git a/tests/playwright/studio-e2e/002_test_sandbox_chatqna.spec.ts b/tests/playwright/studio-e2e/002_test_sandbox_chatqna.spec.ts
index 3f2583a..056e3e6 100644
--- a/tests/playwright/studio-e2e/002_test_sandbox_chatqna.spec.ts
+++ b/tests/playwright/studio-e2e/002_test_sandbox_chatqna.spec.ts
@@ -37,12 +37,19 @@ async function setupResponseListener(page, apiResponse) {
});
}
-test('002_test_sandbox_chatqna', async ({ page, baseURL }) => {
+test('002_test_sandbox_chatqna', async ({ browser, baseURL }) => {
test.setTimeout(600000);
let apiResponse = { value: '' };
-
+ const context = await browser.newContext({
+ ignoreHTTPSErrors: true
+ });
+ const page = await context.newPage();
const IDC_URL = baseURL || ""
await page.goto(IDC_URL);
+ await page.getByLabel('Username or email').fill('test_automation@gmail.com');
+ await page.getByLabel('Password', { exact: true }).click();
+ await page.getByLabel('Password', { exact: true }).fill('test');
+ await page.getByRole('button', { name: 'Sign In' }).click();
await page.getByRole('button', { name: 'Create New Workflow' }).click();
await page.getByRole('button', { name: 'Settings' }).click();
let fileChooserPromise = page.waitForEvent('filechooser');