- Created by YUKA SAITO , last modified on Jul 31, 2024
You are viewing an old version of this page. View the current version.
Compare with Current View Version History
« Previous Version 2 Next »
クライアントソース置換は、プライマリー組織からの共有コンテンツを閲覧する際に、各クライアント組織に個別のデータソースを使用するためのメカニズムです。これにより、最小限の構成で、レポートやダッシュボードの単一のコピーを、各クライアントがそれぞれのデータで使用できます。
一般的なシナリオは、新しいテナントがYellowfin インスタンスにオンボーディングされ、そのテナントのデータに対するレポートを有効にする必要がある場合です。このプロセスには、いくつかの手順が含まれます。
- データソースをクライアント組織で作成する必要があります。
- 新しいクライアントデータソースは、すべての共有コンテンツが作成されたプライマリー組織にリンクされている必要があります。
クライアント組織で新しいデータソースを作成するには、2つの方法があります。既存のデータソースのコピーをインポートすることで、クライアントのデータソースを作成することができます。データソースを直接作成するエンドポイントもあります。
データソースが作成されると、クライアントデータソースをプライマリー組織のデータソースに関連付けるためのエンドポイントが1つ用意されます。
複製したインポートからデータソースを作成
新しいクライアント組織に新しいデータソースを作成する1つの方法は、既存のデータソースを複製し、新しい接続のために接続詳細を変更することです。これは、既存のデータソースをエクスポートし、エクスポートファイル自体を変更して、Yellowfinに再インポートすることで実現できます。
ソース置換を使用する場合、プライマリー組織に既にプレースホルダーデータソースがあり、そこにすべてのレポートコンテンツが存在している必要があります。このデータソースは、Yellowfin内のエクスポートUIを使用してエクスポートできます。これにより、YellowfinからYFX形式のファイルがエクスポートされます。
YFXファイルは、解凍可能なアーカイブ (zip) ファイルです。YFXファイル内には、ExportListHierarchy.json ファイルと、YFExport.xml ファイルがあります。YFExport.xml ファイルには、エクスポートされたデータソースの読み取り可能なバージョンが含まれています。
YFExport.xml ファイル内では、データベース接続設定を変更できます。ソース置換用のテナントデータソースの作成プロセスを自動化する場合は、YFExport.xml ファイルのコンテンツをテンプレートとして使用し、接続固有のデータを注入する必要がある場所にトークンを追加します。
以下のYFExport.xml ファイルの抜粋は、クライアントソース置換で使用するデータソースを自動生成するプロセスでトークンを置き換える箇所を赤で示しています。
<source> <id>132641</id> <sourceName>PostgreSQL Connection for [TENANT_NAME]</sourceName> <sourceDescription>PostgreSQL Connection for [TENANT_NAME]</sourceDescription> <databasePath>public</databasePath> <userName>[USERNAME]</userName> <password>[ENCRYPTED_PASSWORD]</password> <connectionTypeCode>GENERICUSER</connectionTypeCode> <connectionMethodCode>JDBC</connectionMethodCode> <connectionDriver>org.postgresql.Driver</connectionDriver> <databaseURL>jdbc:postgresql://[SERVER_ADDRESS]:5432/[DATABASE_NAME]></databaseURL> <databaseTypeCode>POSTGRESQL</databaseTypeCode> <minConnections>1</minConnections> <maxConnections>5</maxConnections> <connectionRefreshTime>180</connectionRefreshTime> <connectionTimeOut>180</connectionTimeOut> <accessCode>UNSECURE</accessCode> <maxRowCount>10000</maxRowCount> <maxAnalysisRowCount>0</maxAnalysisRowCount> <broadcastPermitted>true</broadcastPermitted> <subscribePermitted>true</subscribePermitted> <dataProfileEnabled>true</dataProfileEnabled> <localTimezoneCode>AUSTRALIA/LORD_HOWE</localTimezoneCode> <secondaryMinConnections>0</secondaryMinConnections> <secondaryMaxConnections>0</secondaryMaxConnections> <secondaryConnectionRefreshTime>0</secondaryConnectionRefreshTime> <secondaryConnectionTimeOut>0</secondaryConnectionTimeOut> <lastModifiedGMTDateTime>20240607025556.000000</lastModifiedGMTDateTime> <sourceUUID>7d7543c0-e9c7-4a80-ab14-73181e4d0694</sourceUUID> <filterList/> <sourceParameterList> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>DATABASE</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>[DATABASE_NAME]</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>HOSTNAME</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>[SERVER_ADDRESS]</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter>
エクスポートファイルを自動的にトークンに挿入したら、POST /api/rpc/import-export/import-content エンドポイント Import Content を使用してREST API経由でアップロードできます。
この特定のエンドポイントは、フォームベースの送信パラダイムを使用します。2つのフォーム本体が必要であり、1つはYFX/XML ファイルコンテンツを含む「contentToProcess」という名前で、もう1つは、インポート処理に関するルールを含む「importOptions」という名前です。こちらの例では、XMLファイルに単一のデータソースが含まれていると仮定して、この importOptions ペイロードを使用できます。
[ { "itemIndex": 0, "optionKey": "SKIP", "optionValue": false }, { "itemIndex": 0, "optionKey": "OPTION\", "optionValue": "ADD" } ]
以下のコード例では、事前にエクスポートされたデータベースXMLテンプレートを使用して、データベースホスト、データベース名、データベースユーザーとパスワードの置換値をファイルに挿入します。その後、(クライアント参照IDで指定された) テナントにインポートされます。
package rest.code.examples; import java.io.IOException; import java.nio.charset.Charset; import java.util.Random; import org.apache.hc.client5.http.entity.mime.HttpMultipartMode; import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder; import org.apache.hc.client5.http.fluent.Content; import org.apache.hc.client5.http.fluent.Request; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpEntity; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; /** * Import a datasource for a client org using the Yellowfin REST API */ public class ImportDatasourceForClientOrg { public static void main(String[] args) throws Exception { System.out.print("Import Datasource for Client"); String host = "http://localhost:8080/Yellowfin"; String restUsername = "admin@yellowfin.com.au"; String restPassword = "test"; String tenantClientReferenceId = "NEWCLIENT"; String databaseUserName = "postgres"; String encryptedPassword = "NDliYzg3NGItMDVjJVY8ywTSdIE3D1zdGplLLBUcEFqw"; String serverAddress = "localhost"; String databaseName = "testdata"; String token = generateTokenForTenant(host, restUsername, restPassword, tenantClientReferenceId); Integer tenantId = retrieveTenantIpIdForTenantName(host, token, tenantClientReferenceId); System.out.println("Tenant Id: " + tenantId); // Replace tokens with values String modifiedFileContents = importFileContents; modifiedFileContents = modifiedFileContents.replace("[USERNAME]", databaseUserName); modifiedFileContents = modifiedFileContents.replace("[TENANT_NAME]", tenantClientReferenceId); modifiedFileContents = modifiedFileContents.replace("[ENCRYPTED_PASSWORD]", encryptedPassword); modifiedFileContents = modifiedFileContents.replace("[SERVER_ADDRESS]", serverAddress); modifiedFileContents = modifiedFileContents.replace("[DATABASE_NAME]", databaseName); HttpEntity multipartEntity = MultipartEntityBuilder .create() .setMode(HttpMultipartMode.LEGACY) .setCharset(Charset.forName("UTF-8")) .addBinaryBody("contentToProcess", modifiedFileContents.getBytes("UTF-8"), ContentType.DEFAULT_BINARY, "YFExport.xml") .addTextBody("importOptions", "[{ \"itemIndex\": 0, \"optionKey\": \"SKIP\", \"optionValue\": false }, { \"itemIndex\": 0, \"optionKey\": \"OPTION\", \"optionValue\": \"ADD\" }]", ContentType.APPLICATION_JSON) .build(); System.out.println("Content-Type: " + multipartEntity.getContentType()); Content c = Request.post(host + "/api/rpc/import-export/import-content") .addHeader("Authorization", "YELLOWFIN ts=" + System.currentTimeMillis() + " , nonce=" + new Random().nextLong() + ", token=" + token) .addHeader("Accept", "application/vnd.yellowfin.api-v1+json") .addHeader("Content-Type", multipartEntity.getContentType()) .addHeader("cache-control", "no-cache") .body(multipartEntity) .execute() .returnContent(); System.out.println(c.asString()); } /* * This function fetches a client organization's integer id for a given clientRefCode */ public static Integer retrieveTenantIpIdForTenantName(String host, String token, String tenantCode) throws IOException { Content c = Request.get(host + "/api/orgs") .addHeader("Authorization", "YELLOWFIN ts=" + System.currentTimeMillis() + " , nonce=" + new Random().nextLong() + ", token=" + token) .addHeader("Accept", "application/vnd.yellowfin.api-v1+json") .addHeader("Content-Type", "application/json") .execute().returnContent(); JsonObject jsonObject = new JsonParser().parse(c.asString()).getAsJsonObject(); JsonElement groupList = jsonObject.get("items"); JsonArray groups = groupList.getAsJsonArray(); for (int i=0; i < groups.size(); i++ ) { JsonObject group = groups.getAsJsonArray().get(i).getAsJsonObject(); if (!group.has("clientRefId")) continue; if (tenantCode.equals(group.get("clientRefId").getAsString())) return group.get("ipOrg").getAsInt(); } System.out.println("Tenant could not be found for code:" + tenantCode); System.exit(-1); return null; } /* * This function generates an access token for a user that will grant them access to * call REST API endpoints. */ public static String generateTokenForTenant(String host, String username, String password, String tenant) throws IOException { Content c = Request.post(host + "/api/refresh-tokens") .addHeader("Authorization", "YELLOWFIN ts=" + System.currentTimeMillis() + " , nonce=" + new Random().nextLong()) .addHeader("Accept", "application/vnd.yellowfin.api-v1+json") .addHeader("Content-Type", "application/json") .bodyString("{ \"userName\": \""+ username + "\",\"password\": \""+ password + "\", \"clientOrgRef\": \"" + tenant + "\"}", null) .execute().returnContent(); JsonObject jsonObject = new JsonParser().parse(c.asString()).getAsJsonObject(); JsonElement accessToken = jsonObject.getAsJsonObject("_embedded").getAsJsonObject("accessToken").get("securityToken"); if (accessToken!=null) { System.out.println("Access Token: " + accessToken); } else { System.out.println("Token not retrieved successfully"); System.exit(-1); } return accessToken.getAsString(); } private static String importFileContents = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!-- Yellowfin export file --><!-- Generated at 2024-06-07 12:56 AEST (+1000) --><data>\n" + " <info>\n" + " <exportversion>4</exportversion>\n" + " <exportsubversion>54</exportsubversion>\n" + " <transferHeaderUUID>c072afce-d02a-4b2c-ae06-c3b62c8d6ea8</transferHeaderUUID>\n" + " <appversion>9.11</appversion>\n" + " <appsubversion>0.3</appsubversion>\n" + " <buildversion>20240607</buildversion>\n" + " <exportdate>2024-06-07 12:56 AEST (+1000)</exportdate>\n" + " <systemid>9e/Rsd4Jf6UwZGq/5Q8Ej1Giviw=</systemid>\n" + " </info>\n" + " <source>\n" + " <id>132641</id>\n" + " <sourceName>PostgreSQL Connection for [TENANT_NAME]</sourceName>\n" + " <sourceDescription>PostgreSQL Connection for [TENANT_NAME]</sourceDescription>\n" + " <databasePath>public</databasePath>\n" + " <userName>[USERNAME]</userName>\n" + " <password>[ENCRYPTED_PASSWORD]</password>\n" + " <connectionTypeCode>GENERICUSER</connectionTypeCode>\n" + " <connectionMethodCode>JDBC</connectionMethodCode>\n" + " <connectionDriver>org.postgresql.Driver</connectionDriver>\n" + " <databaseURL>jdbc:postgresql://[SERVER_ADDRESS]:5432/[DATABASE_NAME]></databaseURL>\n" + " <databaseTypeCode>POSTGRESQL</databaseTypeCode>\n" + " <minConnections>1</minConnections>\n" + " <maxConnections>5</maxConnections>\n" + " <connectionRefreshTime>180</connectionRefreshTime>\n" + " <connectionTimeOut>180</connectionTimeOut>\n" + " <accessCode>UNSECURE</accessCode>\n" + " <maxRowCount>10000</maxRowCount>\n" + " <maxAnalysisRowCount>0</maxAnalysisRowCount>\n" + " <broadcastPermitted>true</broadcastPermitted>\n" + " <subscribePermitted>true</subscribePermitted>\n" + " <dataProfileEnabled>true</dataProfileEnabled>\n" + " <localTimezoneCode>AUSTRALIA/LORD_HOWE</localTimezoneCode>\n" + " <secondaryMinConnections>0</secondaryMinConnections>\n" + " <secondaryMaxConnections>0</secondaryMaxConnections>\n" + " <secondaryConnectionRefreshTime>0</secondaryConnectionRefreshTime>\n" + " <secondaryConnectionTimeOut>0</secondaryConnectionTimeOut>\n" + " <lastModifiedGMTDateTime>20240607025556.000000</lastModifiedGMTDateTime>\n" + " <sourceUUID>7d7543c0-e9c7-4a80-ab14-73181e4d0694</sourceUUID>\n" + " <filterList/>\n" + " <sourceParameterList>\n" + " <sourceParameter>\n" + " <id>0</id>\n" + " <parameterTypeCode>TEXT</parameterTypeCode>\n" + " <parameterKey>DATABASE</parameterKey>\n" + " <parameterIndex>0</parameterIndex>\n" + " <parameterValue>[DATABASE_NAME]</parameterValue>\n" + " <documentId>0</documentId>\n" + " <userVisible>true</userVisible>\n" + " </sourceParameter>\n" + " <sourceParameter>\n" + " <id>0</id>\n" + " <parameterTypeCode>TEXT</parameterTypeCode>\n" + " <parameterKey>HOSTNAME</parameterKey>\n" + " <parameterIndex>0</parameterIndex>\n" + " <parameterValue>[SERVER_ADDRESS]</parameterValue>\n" + " <documentId>0</documentId>\n" + " <userVisible>true</userVisible>\n" + " </sourceParameter>\n" + " <sourceParameter>\n" + " <id>0</id>\n" + " <parameterTypeCode>TEXT</parameterTypeCode>\n" + " <parameterKey>ISOLATIONLEVEL</parameterKey>\n" + " <parameterIndex>0</parameterIndex>\n" + " <parameterValue/>\n" + " <documentId>0</documentId>\n" + " <userVisible>true</userVisible>\n" + " </sourceParameter>\n" + " <sourceParameter>\n" + " <id>0</id>\n" + " <parameterTypeCode>TEXT</parameterTypeCode>\n" + " <parameterKey>PORT</parameterKey>\n" + " <parameterIndex>0</parameterIndex>\n" + " <parameterValue>5432</parameterValue>\n" + " <documentId>0</documentId>\n" + " <userVisible>true</userVisible>\n" + " </sourceParameter>\n" + " <sourceParameter>\n" + " <id>0</id>\n" + " <parameterTypeCode>TEXT</parameterTypeCode>\n" + " <parameterKey>SOURCECLASSNAME</parameterKey>\n" + " <parameterIndex>0</parameterIndex>\n" + " <parameterValue>com.hof.sources.JDBCSourcePlatformImplementation</parameterValue>\n" + " <documentId>0</documentId>\n" + " <userVisible>false</userVisible>\n" + " </sourceParameter>\n" + " <sourceParameter>\n" + " <id>0</id>\n" + " <parameterTypeCode>TEXT</parameterTypeCode>\n" + " <parameterKey>USESCHEMA</parameterKey>\n" + " <parameterIndex>0</parameterIndex>\n" + " <parameterValue>true</parameterValue>\n" + " <documentId>0</documentId>\n" + " <userVisible>true</userVisible>\n" + " </sourceParameter>\n" + " <sourceParameter>\n" + " <id>0</id>\n" + " <parameterTypeCode>TEXT</parameterTypeCode>\n" + " <parameterKey>YF_DRIVER_SELECTION</parameterKey>\n" + " <parameterIndex>0</parameterIndex>\n" + " <parameterValue>org.postgresql.Driver</parameterValue>\n" + " <documentId>0</documentId>\n" + " <userVisible>true</userVisible>\n" + " </sourceParameter>\n" + " </sourceParameterList>\n" + " </source>\n" + " <translationDictionary/>\n" + " <refCodeDictionary/>\n" + "</data>"; }
using System.Net.Http.Headers; using System.Text; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace YellowfinAPIExamples { public class ImportDatasourceForClientOrg { static async Task Main(string[] args) { Console.WriteLine("Import Datasource for Client"); string host = "http://localhost:8080/Yellowfin"; string restUsername = "admin@yellowfin.com.au"; string restPassword = "test"; string tenantClientReferenceId = "NEWCLIENT"; string databaseUserName = "postgres"; string encryptedPassword = "NDliYzg3NGItMDVjJVY8ywTSdIE3D1zdGplLLBUcEFqw"; string serverAddress = "localhost"; string databaseName = "testdata"; string token = await GenerateTokenForTenant(host, restUsername, restPassword, tenantClientReferenceId); int tenantId = await RetrieveTenantIpIdForTenantName(host, token, tenantClientReferenceId); Console.WriteLine("Tenant Id: " + tenantId); // Replace tokens with values string modifiedFileContents = ImportFileContents; modifiedFileContents = modifiedFileContents.Replace("[USERNAME]", databaseUserName) .Replace("[TENANT_NAME]", tenantClientReferenceId) .Replace("[ENCRYPTED_PASSWORD]", encryptedPassword) .Replace("[SERVER_ADDRESS]", serverAddress) .Replace("[DATABASE_NAME]", databaseName); using (var httpClient = new HttpClient()) { var content = new MultipartFormDataContent { { new ByteArrayContent(Encoding.UTF8.GetBytes(modifiedFileContents)), "contentToProcess", "YFExport.xml" }, { new StringContent( "[{ \"itemIndex\": 0, \"optionKey\": \"SKIP\", \"optionValue\": false }, { \"itemIndex\": 0, \"optionKey\": \"OPTION\", \"optionValue\": \"ADD\" }]", Encoding.UTF8, "application/json"), "importOptions" } }; httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("YELLOWFIN", "ts=" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + " , nonce=" + new Random().NextInt64() + ", token=" + token); httpClient.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/vnd.yellowfin.api-v1+json")); httpClient.DefaultRequestHeaders.Add("cache-control", "no-cache"); HttpResponseMessage response = await httpClient.PostAsync(host + "/api/rpc/import-export/import-content", content); string responseBody = await response.Content.ReadAsStringAsync(); Console.WriteLine(responseBody); } } private static async Task<int> RetrieveTenantIpIdForTenantName(string host, string token, string tenantCode) { using (var httpClient = new HttpClient()) { httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("YELLOWFIN", "ts=" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + " , nonce=" + new Random().NextInt64() + ", token=" + token); httpClient.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/vnd.yellowfin.api-v1+json")); HttpResponseMessage response = await httpClient.GetAsync(host + "/api/orgs"); string responseBody = await response.Content.ReadAsStringAsync(); JObject jsonObject = JsonConvert.DeserializeObject<JObject>(responseBody); JArray groups = (JArray)jsonObject["items"]; foreach (var group in groups) { if (group["clientRefId"] != null && tenantCode == group["clientRefId"].ToString()) { return (int)group["ipOrg"]; } } Console.WriteLine("Tenant could not be found for code:" + tenantCode); Environment.Exit(-1); return 0; } } private static async Task<string> GenerateTokenForTenant(string host, string username, string password, string tenant) { using (var client = new HttpClient()) { var request = new HttpRequestMessage(HttpMethod.Post, host + "/api/refresh-tokens"); request.Headers.Add("Authorization", "YELLOWFIN ts=" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + ", nonce=" + new Random().NextInt64()); request.Headers.Add("Accept", "application/vnd.yellowfin.api-v1+json"); request.Content = new StringContent( JsonConvert.SerializeObject(new { userName = username, password = password, clientOrgRef = tenant }), Encoding.UTF8, "application/json" ); HttpResponseMessage response = await client.SendAsync(request); string responseContent = await response.Content.ReadAsStringAsync(); JObject jsonObject = JsonConvert.DeserializeObject<JObject>(responseContent); string accessToken = jsonObject["_embedded"]["accessToken"]["securityToken"].ToString(); if (!string.IsNullOrEmpty(accessToken)) { Console.WriteLine("Access Token: " + accessToken); } else { Console.WriteLine("Token not retrieved"); Environment.Exit(-1); } return accessToken; } } private static readonly string ImportFileContents = @"<?xml version=""1.0"" encoding=""UTF-8""?><!-- Yellowfin export file --><!-- Generated at 2024-06-07 12:56 AEST (+1000) --><data> <info> <exportversion>4</exportversion> <exportsubversion>54</exportsubversion> <transferHeaderUUID>c072afce-d02a-4b2c-ae06-c3b62c8d6ea8</transferHeaderUUID> <appversion>9.11</appversion> <appsubversion>0.3</appsubversion> <buildversion>20240607</buildversion> <exportdate>2024-06-07 12:56 AEST (+1000)</exportdate> <systemid>9e/Rsd4Jf6UwZGq/5Q8Ej1Giviw=</systemid> </info> <source> <id>132641</id> <sourceName>PostgreSQL Connection for [TENANT_NAME]</sourceName> <sourceDescription>PostgreSQL Connection for [TENANT_NAME]</sourceDescription> <databasePath>public</databasePath> <userName>[USERNAME]</userName> <password>[ENCRYPTED_PASSWORD]</password> <connectionTypeCode>GENERICUSER</connectionTypeCode> <connectionMethodCode>JDBC</connectionMethodCode> <connectionDriver>org.postgresql.Driver</connectionDriver> <databaseURL>jdbc:postgresql://[SERVER_ADDRESS]:5432/[DATABASE_NAME]></databaseURL> <databaseTypeCode>POSTGRESQL</databaseTypeCode> <minConnections>1</minConnections> <maxConnections>5</maxConnections> <connectionRefreshTime>180</connectionRefreshTime> <connectionTimeOut>180</connectionTimeOut> <accessCode>UNSECURE</accessCode> <maxRowCount>10000</maxRowCount> <maxAnalysisRowCount>0</maxAnalysisRowCount> <broadcastPermitted>true</broadcastPermitted> <subscribePermitted>true</subscribePermitted> <dataProfileEnabled>true</dataProfileEnabled> <localTimezoneCode>AUSTRALIA/LORD_HOWE</localTimezoneCode> <secondaryMinConnections>0</secondaryMinConnections> <secondaryMaxConnections>0</secondaryMaxConnections> <secondaryConnectionRefreshTime>0</secondaryConnectionRefreshTime> <secondaryConnectionTimeOut>0</secondaryConnectionTimeOut> <lastModifiedGMTDateTime>20240607025556.000000</lastModifiedGMTDateTime> <sourceUUID>7d7543c0-e9c7-4a80-ab14-73181e4d0694</sourceUUID> <filterList/> <sourceParameterList> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>DATABASE</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>[DATABASE_NAME]</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>HOSTNAME</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>[SERVER_ADDRESS]</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>ISOLATIONLEVEL</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue/> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>PORT</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>5432</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>SOURCECLASSNAME</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>com.hof.sources.JDBCSourcePlatformImplementation</parameterValue> <documentId>0</documentId> <userVisible>false</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>USESCHEMA</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>true</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>YF_DRIVER_SELECTION</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>org.postgresql.Driver</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> </sourceParameterList> </source> <translationDictionary/> <refCodeDictionary/> </data>"; } }
package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "math/rand" "mime/multipart" "net/http" "strings" "time" ) func main() { host := "http://localhost:8080/Yellowfin" restUsername := "admin@yellowfin.com.au" restPassword := "test" tenantClientReferenceId := "NEWCLIENT" databaseUserName := "postgres" encryptedPassword := "NDliYzg3NGItMDVjJVY8ywTSdIE3D1zdGplLLBUcEFqw" serverAddress := "localhost" databaseName := "testdata" token, err := generateToken(host, restUsername, restPassword, tenantClientReferenceId) if err != nil { fmt.Println("Error generating token:", err) return } tenantId, err := retrieveTenantIpIdForTenantName(host, token, tenantClientReferenceId) if err != nil { fmt.Println("Error retrieving tenant ID:", err) return } fmt.Println("Tenant Id:", tenantId) // Replace tokens with values modifiedFileContents := strings.Replace(importFileContents, "[USERNAME]", databaseUserName, -1) modifiedFileContents = strings.Replace(modifiedFileContents, "[TENANT_NAME]", tenantClientReferenceId, -1) modifiedFileContents = strings.Replace(modifiedFileContents, "[ENCRYPTED_PASSWORD]", encryptedPassword, -1) modifiedFileContents = strings.Replace(modifiedFileContents, "[SERVER_ADDRESS]", serverAddress, -1) modifiedFileContents = strings.Replace(modifiedFileContents, "[DATABASE_NAME]", databaseName, -1) bodyBuffer := &bytes.Buffer{} writer := multipart.NewWriter(bodyBuffer) // Add file content part, err := writer.CreateFormFile("contentToProcess", "YFExport.xml") if err != nil { fmt.Println("Error creating form file:", err) return } part.Write([]byte(modifiedFileContents)) // Add text body err = writer.WriteField("importOptions", `[{"itemIndex": 0, "optionKey": "SKIP", "optionValue": false}, {"itemIndex": 0, "optionKey": "OPTION", "optionValue": "ADD"}]`) if err != nil { fmt.Println("Error writing field:", err) return } writer.Close() client := &http.Client{} req, err := http.NewRequest("POST", host+"/api/rpc/import-export/import-content", bodyBuffer) if err != nil { fmt.Println("Error creating request:", err) return } nonce := rand.Int63() req.Header.Set("Authorization", fmt.Sprintf("YELLOWFIN ts=%d, nonce=%d, token=%s", time.Now().UnixMilli(), nonce, token)) req.Header.Set("Accept", "application/vnd.yellowfin.api-v1+json") req.Header.Set("Content-Type", writer.FormDataContentType()) req.Header.Set("cache-control", "no-cache") resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response body:", err) return } fmt.Println(string(body)) } func generateToken(host, restUsername, restPassword, tenant string) (string, error) { nonce := rand.Int63() requestBody, err := json.Marshal(map[string]string{ "userName": restUsername, "password": restPassword, "clientOrgRef": tenant, }) if err != nil { fmt.Println("Error marshaling request body:", err) return "", err } client := &http.Client{} request, err := http.NewRequest("POST", host+"/api/refresh-tokens", bytes.NewBuffer(requestBody)) if err != nil { fmt.Println("Error creating request:", err) return "", err } request.Header.Set("Authorization", fmt.Sprintf("YELLOWFIN ts=%d, nonce=%d", time.Now().UnixMilli(), nonce)) request.Header.Set("Accept", "application/vnd.yellowfin.api-v1+json") request.Header.Set("Content-Type", "application/json") response, err := client.Do(request) if err != nil { fmt.Println("Error sending request:", err) return "", err } defer response.Body.Close() responseBody, err := ioutil.ReadAll(response.Body) if err != nil { fmt.Println("Error reading response body:", err) return "", err } var jsonResponse map[string]interface{} err = json.Unmarshal(responseBody, &jsonResponse) if err != nil { fmt.Println("Error parsing JSON response:", err) return "", err } accessToken, ok := jsonResponse["_embedded"].(map[string]interface{})["accessToken"].(map[string]interface{})["securityToken"].(string) if !ok { fmt.Println("Token not retrieved") return "", fmt.Errorf("Token not retrieved successfully") } return accessToken, nil } func retrieveTenantIpIdForTenantName(host, token, tenantCode string) (int, error) { client := &http.Client{} req, err := http.NewRequest("GET", host+"/api/orgs", nil) if err != nil { return 0, err } nonce := rand.Int63() req.Header.Set("Authorization", fmt.Sprintf("YELLOWFIN ts=%d, nonce=%d, token=%s", time.Now().UnixMilli(), nonce, token)) req.Header.Set("Accept", "application/vnd.yellowfin.api-v1+json") req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { return 0, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return 0, err } var jsonResponse map[string]interface{} err = json.Unmarshal(body, &jsonResponse) if err != nil { return 0, err } items, ok := jsonResponse["items"].([]interface{}) if !ok { return 0, fmt.Errorf("Invalid response format") } for _, item := range items { group, ok := item.(map[string]interface{}) if !ok { continue } if group["clientRefId"] == tenantCode { return int(group["ipOrg"].(float64)), nil } } return 0, fmt.Errorf("Tenant could not be found for code: %s", tenantCode) } const importFileContents = `<?xml version="1.0" encoding="UTF-8"?><!-- Yellowfin export file --><!-- Generated at 2024-06-07 12:56 AEST (+1000) --><data> <info> <exportversion>4</exportversion> <exportsubversion>54</exportsubversion> <transferHeaderUUID>c072afce-d02a-4b2c-ae06-c3b62c8d6ea8</transferHeaderUUID> <appversion>9.11</appversion> <appsubversion>0.3</appsubversion> <buildversion>20240607</buildversion> <exportdate>2024-06-07 12:56 AEST (+1000)</exportdate> <systemid>9e/Rsd4Jf6UwZGq/5Q8Ej1Giviw=</systemid> </info> <source> <id>132641</id> <sourceName>PostgreSQL Connection for [TENANT_NAME]</sourceName> <sourceDescription>PostgreSQL Connection for [TENANT_NAME]</sourceDescription> <databasePath>public</databasePath> <userName>[USERNAME]</userName> <password>[ENCRYPTED_PASSWORD]</password> <connectionTypeCode>GENERICUSER</connectionTypeCode> <connectionMethodCode>JDBC</connectionMethodCode> <connectionDriver>org.postgresql.Driver</connectionDriver> <databaseURL>jdbc:postgresql://[SERVER_ADDRESS]:5432/[DATABASE_NAME]></databaseURL> <databaseTypeCode>POSTGRESQL</databaseTypeCode> <minConnections>1</minConnections> <maxConnections>5</maxConnections> <connectionRefreshTime>180</connectionRefreshTime> <connectionTimeOut>180</connectionTimeOut> <accessCode>UNSECURE</accessCode> <maxRowCount>10000</maxRowCount> <maxAnalysisRowCount>0</maxAnalysisRowCount> <broadcastPermitted>true</broadcastPermitted> <subscribePermitted>true</subscribePermitted> <dataProfileEnabled>true</dataProfileEnabled> <localTimezoneCode>AUSTRALIA/LORD_HOWE</localTimezoneCode> <secondaryMinConnections>0</secondaryMinConnections> <secondaryMaxConnections>0</secondaryMaxConnections> <secondaryConnectionRefreshTime>0</secondaryConnectionRefreshTime> <secondaryConnectionTimeOut>0</secondaryConnectionTimeOut> <lastModifiedGMTDateTime>20240607025556.000000</lastModifiedGMTDateTime> <sourceUUID>7d7543c0-e9c7-4a80-ab14-73181e4d0694</sourceUUID> <filterList/> <sourceParameterList> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>DATABASE</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>[DATABASE_NAME]</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>HOSTNAME</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>[SERVER_ADDRESS]</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>ISOLATIONLEVEL</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue/> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>PORT</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>5432</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>SOURCECLASSNAME</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>com.hof.sources.JDBCSourcePlatformImplementation</parameterValue> <documentId>0</documentId> <userVisible>false</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>USESCHEMA</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>true</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>YF_DRIVER_SELECTION</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>org.postgresql.Driver</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> </sourceParameterList> </source> <translationDictionary/> <refCodeDictionary/> </data> `
const fetch = require("node-fetch"); const FormData = require("form-data"); const { Buffer } = require('buffer'); async function main() { console.log("Import Datasource for Client"); const host = "http://localhost:8080/Yellowfin"; const restUsername = "admin@yellowfin.com.au"; const restPassword = "test"; const tenantClientReferenceId = "NEWCLIENT"; const databaseUserName = "postgres"; const encryptedPassword = "NDliYzg3NGItMDVjJVY8ywTSdIE3D1zdGplLLBUcEFqw"; const serverAddress = "localhost"; const databaseName = "testdata"; const token = await generateTokenForTenant(host, restUsername, restPassword, tenantClientReferenceId); if (!token) { console.error("Failed to retrieve access token"); return; } const tenantId = await retrieveTenantIpIdForTenantName(host, token, tenantClientReferenceId); console.log("Tenant Id:", tenantId); // Replace tokens with values let modifiedFileContents = importFileContents; modifiedFileContents = modifiedFileContents.replace("[USERNAME]", databaseUserName); modifiedFileContents = modifiedFileContents.replace("[TENANT_NAME]", tenantClientReferenceId); modifiedFileContents = modifiedFileContents.replace("[ENCRYPTED_PASSWORD]", encryptedPassword); modifiedFileContents = modifiedFileContents.replace("[SERVER_ADDRESS]", serverAddress); modifiedFileContents = modifiedFileContents.replace("[DATABASE_NAME]", databaseName); const formData = new FormData(); formData.append('contentToProcess', Buffer.from(modifiedFileContents), { filename: 'YFExport.xml' }); formData.append('importOptions', JSON.stringify([ { itemIndex: 0, optionKey: "SKIP", optionValue: false }, { itemIndex: 0, optionKey: "OPTION", optionValue: "ADD" } ])); const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); const headers = { 'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}, token=${token}`, 'Accept': 'application/vnd.yellowfin.api-v1+json', 'cache-control': 'no-cache' }; try { const response = await fetch(`${host}/api/rpc/import-export/import-content`, { method: 'POST', headers: headers, body: formData }); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const responseBody = await response.text(); console.log(responseBody); } catch (error) { console.error("Error:", error.message); } } async function retrieveTenantIpIdForTenantName(host, token, tenantCode) { const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); const headers = { 'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}, token=${token}`, 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' }; try { const response = await fetch(`${host}/api/orgs`, { method: 'GET', headers: headers }); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const jsonResponse = await response.json(); const groups = jsonResponse.items; for (const group of groups) { if (group.clientRefId && tenantCode === group.clientRefId) { return group.ipOrg; } } console.log("Tenant could not be found for code:", tenantCode); process.exit(-1); } catch (error) { console.error("Error:", error.message); } return null; } async function generateTokenForTenant(host, username, password, tenant) { const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); const headers = { 'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}`, 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' }; const body = JSON.stringify({ userName: username, password: password, clientOrgRef: tenant }); try { const response = await fetch(`${host}/api/refresh-tokens`, { method: 'POST', headers: headers, body: body }); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const jsonResponse = await response.json(); const accessToken = jsonResponse._embedded.accessToken.securityToken; if (accessToken) { console.log(`Access Token: ${accessToken}`); return accessToken; } else { console.log("Token not retrieved successfully"); process.exit(-1); } } catch (error) { console.error("Error:", error.message); } return null; } const importFileContents = `<?xml version="1.0" encoding="UTF-8"?><!-- Yellowfin export file --><!-- Generated at 2024-06-07 12:56 AEST (+1000) --> <data> <info> <exportversion>4</exportversion> <exportsubversion>54</exportsubversion> <transferHeaderUUID>c072afce-d02a-4b2c-ae06-c3b62c8d6ea8</transferHeaderUUID> <appversion>9.11</appversion> <appsubversion>0.3</appsubversion> <buildversion>20240607</buildversion> <exportdate>2024-06-07 12:56 AEST (+1000)</exportdate> <systemid>9e/Rsd4Jf6UwZGq/5Q8Ej1Giviw=</systemid> </info> <source> <id>132641</id> <sourceName>PostgreSQL Connection for [TENANT_NAME]</sourceName> <sourceDescription>PostgreSQL Connection for [TENANT_NAME]</sourceDescription> <databasePath>public</databasePath> <userName>[USERNAME]</userName> <password>[ENCRYPTED_PASSWORD]</password> <connectionTypeCode>GENERICUSER</connectionTypeCode> <connectionMethodCode>JDBC</connectionMethodCode> <connectionDriver>org.postgresql.Driver</connectionDriver> <databaseURL>jdbc:postgresql://[SERVER_ADDRESS]:5432/[DATABASE_NAME]></databaseURL> <databaseTypeCode>POSTGRESQL</databaseTypeCode> <minConnections>1</minConnections> <maxConnections>5</maxConnections> <connectionRefreshTime>180</connectionRefreshTime> <connectionTimeOut>180</connectionTimeOut> <accessCode>UNSECURE</accessCode> <maxRowCount>10000</maxRowCount> <maxAnalysisRowCount>0</maxAnalysisRowCount> <broadcastPermitted>true</broadcastPermitted> <subscribePermitted>true</subscribePermitted> <dataProfileEnabled>true</dataProfileEnabled> <localTimezoneCode>AUSTRALIA/LORD_HOWE</localTimezoneCode> <secondaryMinConnections>0</secondaryMinConnections> <secondaryMaxConnections>0</secondaryMaxConnections> <secondaryConnectionRefreshTime>0</secondaryConnectionRefreshTime> <secondaryConnectionTimeOut>0</secondaryConnectionTimeOut> <lastModifiedGMTDateTime>20240607025556.000000</lastModifiedGMTDateTime> <sourceUUID>7d7543c0-e9c7-4a80-ab14-73181e4d0694</sourceUUID> <filterList/> <sourceParameterList> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>DATABASE</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>[DATABASE_NAME]</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>HOSTNAME</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>[SERVER_ADDRESS]</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>ISOLATIONLEVEL</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue/> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>PORT</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>5432</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>SOURCECLASSNAME</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>com.hof.sources.JDBCSourcePlatformImplementation</parameterValue> <documentId>0</documentId> <userVisible>false</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>USESCHEMA</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>true</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>YF_DRIVER_SELECTION</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>org.postgresql.Driver</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> </sourceParameterList> </source> <translationDictionary/> <refCodeDictionary/> </data> `; main().catch(console.error);
<?php function main($importFileContents) { $host = "http://localhost:8080/Yellowfin"; $restUsername = "admin@yellowfin.com.au"; $restPassword = "test"; try { $token = generateTokenForTenant($host, $restUsername, $restPassword, "NEWCLIENT"); $tenantClientReferenceId = "NEWCLIENT"; $databaseUserName = "postgres"; $encryptedPassword = "NDliYzg3NGItMDVjJVY8ywTSdIE3D1zdGplLLBUcEFqw"; $serverAddress = "localhost"; $databaseName = "testdata"; // Replace tokens with values $modifiedFileContents = $importFileContents; $modifiedFileContents = str_replace("[USERNAME]", $databaseUserName, $modifiedFileContents); $modifiedFileContents = str_replace("[TENANT_NAME]", $tenantClientReferenceId, $modifiedFileContents); $modifiedFileContents = str_replace("[ENCRYPTED_PASSWORD]", $encryptedPassword, $modifiedFileContents); $modifiedFileContents = str_replace("[SERVER_ADDRESS]", $serverAddress, $modifiedFileContents); $modifiedFileContents = str_replace("[DATABASE_NAME]", $databaseName, $modifiedFileContents); // Build multipart entity $multipartEntity = buildMultipartEntity($modifiedFileContents); // Make HTTP request $response = sendMultipartRequest($host, $token, $multipartEntity); echo $response; } catch (Exception $e) { echo "Error: " . $e->getMessage(); } } function generateTokenForTenant($host, $username, $password, $tenant) { // Generate nonce $nonce = mt_rand(); // Create request body $requestBody = json_encode(array( "userName" => $username, "password" => $password, "clientOrgRef" => $tenant )); // Create request headers $headers = array( 'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . $nonce, 'Accept: application/vnd.yellowfin.api-v1+json', 'Content-Type: application/json' ); $response = httpRequest('POST', "$host/api/refresh-tokens", $headers, $requestBody); // Parse JSON response $jsonResponse = json_decode($response, true); // Get access token from response if (isset($jsonResponse["_embedded"]["accessToken"]["securityToken"])) { $accessToken = $jsonResponse["_embedded"]["accessToken"]["securityToken"]; echo "Access Token: " . $accessToken; return $accessToken; } else { throw new Exception("Token not retrieved successfully"); } } function buildMultipartEntity($fileContents) { // Build multipart entity $boundary = uniqid(); $multipartBody = "--$boundary\r\n"; $multipartBody .= 'Content-Disposition: form-data; name="contentToProcess"; filename="YFExport.xml"' . "\r\n"; $multipartBody .= "Content-Type: application/xml\r\n\r\n"; $multipartBody .= $fileContents . "\r\n"; $multipartBody .= "--$boundary\r\n"; $multipartBody .= 'Content-Disposition: form-data; name="importOptions"' . "\r\n"; $multipartBody .= "Content-Type: application/json\r\n\r\n"; $multipartBody .= '[{ "itemIndex": 0, "optionKey": "SKIP", "optionValue": false }, { "itemIndex": 0, "optionKey": "OPTION", "optionValue": "ADD" }]' . "\r\n"; $multipartBody .= "--$boundary--"; return $multipartBody; } function sendMultipartRequest($host, $token, $multipartBody) { $headers = array( 'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . mt_rand() . ', token=' . $token, 'Accept: application/vnd.yellowfin.api-v1+json', 'Content-Type: multipart/form-data; boundary=' . substr($multipartBody, 2, strpos($multipartBody, "\r\n") - 2), 'cache-control: no-cache' ); try { $response = httpRequest('POST', "$host/api/rpc/import-export/import-content", $headers, $multipartBody); return $response; } catch (Exception $e) { throw new Exception("Error sending request: " . $e->getMessage()); } } function httpRequest($method, $url, $headers, $data = null) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); if ($data !== null) { curl_setopt($ch, CURLOPT_POSTFIELDS, $data); } $response = curl_exec($ch); if (curl_errno($ch)) { throw new Exception('Error: ' . curl_error($ch)); } curl_close($ch); return $response; } $importFileContents = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!-- Yellowfin export file --><!-- Generated at 2024-06-07 12:56 AEST (+1000) --> <data> <info> <exportversion>4</exportversion> <exportsubversion>54</exportsubversion> <transferHeaderUUID>c072afce-d02a-4b2c-ae06-c3b62c8d6ea8</transferHeaderUUID> <appversion>9.11</appversion> <appsubversion>0.3</appsubversion> <buildversion>20240607</buildversion> <exportdate>2024-06-07 12:56 AEST (+1000)</exportdate> <systemid>9e/Rsd4Jf6UwZGq/5Q8Ej1Giviw=</systemid> </info> <source> <id>132641</id> <sourceName>PostgreSQL Connection for [TENANT_NAME]</sourceName> <sourceDescription>PostgreSQL Connection for [TENANT_NAME]</sourceDescription> <databasePath>public</databasePath> <userName>[USERNAME]</userName> <password>[ENCRYPTED_PASSWORD]</password> <connectionTypeCode>GENERICUSER</connectionTypeCode> <connectionMethodCode>JDBC</connectionMethodCode> <connectionDriver>org.postgresql.Driver</connectionDriver> <databaseURL>jdbc:postgresql://[SERVER_ADDRESS]:5432/[DATABASE_NAME]></databaseURL> <databaseTypeCode>POSTGRESQL</databaseTypeCode> <minConnections>1</minConnections> <maxConnections>5</maxConnections> <connectionRefreshTime>180</connectionRefreshTime> <connectionTimeOut>180</connectionTimeOut> <accessCode>UNSECURE</accessCode> <maxRowCount>10000</maxRowCount> <maxAnalysisRowCount>0</maxAnalysisRowCount> <broadcastPermitted>true</broadcastPermitted> <subscribePermitted>true</subscribePermitted> <dataProfileEnabled>true</dataProfileEnabled> <localTimezoneCode>AUSTRALIA/LORD_HOWE</localTimezoneCode> <secondaryMinConnections>0</secondaryMinConnections> <secondaryMaxConnections>0</secondaryMaxConnections> <secondaryConnectionRefreshTime>0</secondaryConnectionRefreshTime> <secondaryConnectionTimeOut>0</secondaryConnectionTimeOut> <lastModifiedGMTDateTime>20240607025556.000000</lastModifiedGMTDateTime> <sourceUUID>7d7543c0-e9c7-4a80-ab14-73181e4d0694</sourceUUID> <filterList/> <sourceParameterList> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>DATABASE</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>[DATABASE_NAME]</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>HOSTNAME</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>[SERVER_ADDRESS]</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>ISOLATIONLEVEL</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue/> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>PORT</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>5432</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>SOURCECLASSNAME</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>com.hof.sources.JDBCSourcePlatformImplementation</parameterValue> <documentId>0</documentId> <userVisible>false</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>USESCHEMA</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>true</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>YF_DRIVER_SELECTION</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>org.postgresql.Driver</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> </sourceParameterList> </source> <translationDictionary/> <refCodeDictionary/> </data> "; main($importFileContents); ?>
import json import random import time import requests from requests.exceptions import RequestException def main(): host = "http://localhost:8080/Yellowfin" rest_username = "admin@yellowfin.com.au" rest_password = "test" tenant_client_reference_id = "NEWCLIENT" database_user_name = "postgres" encrypted_password = "NDliYzg3NGItMDVjJVY8ywTSdIE3D1zdGplLLBUcEFqw" server_address = "localhost" database_name = "testdata" try: token = generate_token(host, rest_username, rest_password, tenant_client_reference_id) tenant_id = retrieve_tenant_id_for_tenant_name(host, token, tenant_client_reference_id) print("Tenant Id:", tenant_id) # Replace tokens with values modified_file_contents = import_file_contents.replace("[USERNAME]", database_user_name) \ .replace("[TENANT_NAME]", tenant_client_reference_id) \ .replace("[ENCRYPTED_PASSWORD]", encrypted_password) \ .replace("[SERVER_ADDRESS]", server_address) \ .replace("[DATABASE_NAME]", database_name) multipart_entity = MultipartEncoder( fields={ 'contentToProcess': ('YFExport.xml', modified_file_contents, 'application/xml'), 'importOptions': json.dumps([ {"itemIndex": 0, "optionKey": "SKIP", "optionValue": False}, {"itemIndex": 0, "optionKey": "OPTION", "optionValue": "ADD"} ]) } ) headers = { 'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={random.randint(0, 2**63 - 1)}, token={token}', 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': multipart_entity.content_type, 'cache-control': 'no-cache' } response = requests.post(f'{host}/api/rpc/import-export/import-content', headers=headers, data=multipart_entity.to_string()) print(f"Content-Type: {multipart_entity.content_type}") print(response.text) except RequestException as e: print(f"Request Exception: {e}") def generate_token(host, username, password, tenant): request_body = json.dumps({ "userName": username, "password": password, "clientOrgRef": tenant }) headers = { 'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={random.randint(0, 2**63 - 1)}', 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' } response = requests.post(f'{host}/api/refresh-tokens', headers=headers, data=request_body) if response.status_code == 200: json_response = response.json() access_token = json_response["_embedded"]["accessToken"]["securityToken"] print("Access Token:", access_token) return access_token else: raise Exception("Token not retrieved successfully") def retrieve_tenant_id_for_tenant_name(host, token, tenant_code): headers = { 'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={random.randint(0, 2**63 - 1)}, token={token}', 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' } response = requests.get(f'{host}/api/orgs', headers=headers) if response.status_code == 200: json_data = response.json() items = json_data.get('items', []) for item in items: if 'clientRefId' in item and item['clientRefId'] == tenant_code: return item['ipOrg'] print(f"Tenant could not be found for code: {tenant_code}") exit(-1) else: raise RequestException(f"Failed to retrieve tenant id. Status code: {response.status_code}") class MultipartEncoder: def __init__(self, fields): self.boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW' self.content_type = f'multipart/form-data; boundary={self.boundary}' self.data = self.encode(fields) def encode(self, fields): lines = [] for key, value in fields.items(): lines.append(f'--{self.boundary}') if isinstance(value, tuple): # file data filename, data, content_type = value lines.append(f'Content-Disposition: form-data; name="{key}"; filename="{filename}"') lines.append(f'Content-Type: {content_type}') lines.append('') lines.append(data) else: # regular form field lines.append(f'Content-Disposition: form-data; name="{key}"') lines.append('') lines.append(value) lines.append(f'--{self.boundary}--') lines.append('') return '\r\n'.join(lines) def to_string(self): return self.data import_file_contents = '''<?xml version="1.0" encoding="UTF-8"?><!-- Yellowfin export file --><!-- Generated at 2024-06-07 12:56 AEST (+1000) --> <data> <info> <exportversion>4</exportversion> <exportsubversion>54</exportsubversion> <transferHeaderUUID>c072afce-d02a-4b2c-ae06-c3b62c8d6ea8</transferHeaderUUID> <appversion>9.11</appversion> <appsubversion>0.3</appsubversion> <buildversion>20240607</buildversion> <exportdate>2024-06-07 12:56 AEST (+1000)</exportdate> <systemid>9e/Rsd4Jf6UwZGq/5Q8Ej1Giviw=</systemid> </info> <source> <id>132641</id> <sourceName>PostgreSQL Connection for [TENANT_NAME]</sourceName> <sourceDescription>PostgreSQL Connection for [TENANT_NAME]</sourceDescription> <databasePath>public</databasePath> <userName>[USERNAME]</userName> <password>[ENCRYPTED_PASSWORD]</password> <connectionTypeCode>GENERICUSER</connectionTypeCode> <connectionMethodCode>JDBC</connectionMethodCode> <connectionDriver>org.postgresql.Driver</connectionDriver> <databaseURL>jdbc:postgresql://[SERVER_ADDRESS]:5432/[DATABASE_NAME]></databaseURL> <databaseTypeCode>POSTGRESQL</databaseTypeCode> <minConnections>1</minConnections> <maxConnections>5</maxConnections> <connectionRefreshTime>180</connectionRefreshTime> <connectionTimeOut>180</connectionTimeOut> <accessCode>UNSECURE</accessCode> <maxRowCount>10000</maxRowCount> <maxAnalysisRowCount>0</maxAnalysisRowCount> <broadcastPermitted>true</broadcastPermitted> <subscribePermitted>true</subscribePermitted> <dataProfileEnabled>true</dataProfileEnabled> <localTimezoneCode>AUSTRALIA/LORD_HOWE</localTimezoneCode> <secondaryMinConnections>0</secondaryMinConnections> <secondaryMaxConnections>0</secondaryMaxConnections> <secondaryConnectionRefreshTime>0</secondaryConnectionRefreshTime> <secondaryConnectionTimeOut>0</secondaryConnectionTimeOut> <lastModifiedGMTDateTime>20240607025556.000000</lastModifiedGMTDateTime> <sourceUUID>7d7543c0-e9c7-4a80-ab14-73181e4d0694</sourceUUID> <filterList/> <sourceParameterList> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>DATABASE</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>[DATABASE_NAME]</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>HOSTNAME</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>[SERVER_ADDRESS]</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>ISOLATIONLEVEL</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue/> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>PORT</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>5432</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>SOURCECLASSNAME</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>com.hof.sources.JDBCSourcePlatformImplementation</parameterValue> <documentId>0</documentId> <userVisible>false</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>USESCHEMA</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>true</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> <sourceParameter> <id>0</id> <parameterTypeCode>TEXT</parameterTypeCode> <parameterKey>YF_DRIVER_SELECTION</parameterKey> <parameterIndex>0</parameterIndex> <parameterValue>org.postgresql.Driver</parameterValue> <documentId>0</documentId> <userVisible>true</userVisible> </sourceParameter> </sourceParameterList> </source> <translationDictionary/> <refCodeDictionary/> </data> ''' if __name__ == "__main__": main()
データソースサービス経由で新しいデータソースを作成
データソースは、POST /api/data-sources エンドポイント Create Data Source を使用して、REST API経由で直接作成することができます。
これは、こちらの形式のデータソースモデルを取ります。
{ "sourceName": "Client Database", "sourceDescription": "", "sourceType": "POSTGRESQL", "connectionType": "JDBC", "connectionTypeCode": "GENERICUSER", "connectionDriver": "org.postgresql.Driver", "connectionString": "jdbc:postgresql://192.168.1.100:5432/testdata", "connectionTimeout": 180, "userName": "postgres", "minimumConnections": 1, "maximumConnections": 5, "refreshTime": 180, "timezone": "AUSTRALIA/SYDNEY", "accessLevelCode": "UNSECURE", "maxRows": 10000, "maxAnalysisRows": 0, "inheritChildSourceFilters": false, "sourceLogIndicator": false, "sourceOptions": [ { "optionKey": "ISOLATIONLEVEL", "optionValue": "1.0", "valueDataType": "1" }, { "optionKey": "USESCHEMA", "optionValue": "true", "valueDataType": "6" }, { "optionKey": "HOSTNAME", "optionValue": "192.168.1.100", "valueDataType": "2" }, { "optionKey": "PORT", "optionValue": "5432", "valueDataType": "1" }, { "optionKey": "DATABASE", "optionValue": "testdata", "valueDataType": "2" }, { "optionKey": "YF_DRIVER_SELECTION", "optionValue": "org.postgresql.Driver", "valueDataType": "2" } ] }
モデルの本体は、GET /api/data-sources エンドポイントによって返されるモデルと似ています。プライマリー組織のデータソースと似た新しいソースを作成する場合は、GET /api/data-sources により返されるデータをテンプレートとして使用できます。
作成モデル内のsourceOptionsは、データベースの種類によって異なり、新しいデータソースに接続する際に接続ウィザードによって公開されるオプションの代表的なものです。
connectionString はモデル本体で使用できますが、データソースの作成時にソースオプションに基づいて再生成されることに注意してください。
以下の例では、POST /api/data-sources エンドポイントを使用して新しいデータソースを作成する方法を示しています。
package rest.code.examples; import java.io.IOException; import java.util.Random; import org.apache.hc.client5.http.fluent.Content; import org.apache.hc.client5.http.fluent.Request; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; /** * Create a datasource using the Yellowfin REST API */ public class CreateADataSource { public static void main(String[] args) throws Exception { String host = "http://localhost:8080/yellowfinHead"; String restUsername = "admin@yellowfin.com.au"; String restPassword = "test"; String createDataSourcePayload = "{\n" + " \"sourceName\": \"PostgreSQL Database Created Via Import\",\n" + " \"sourceDescription\": \"\",\n" + " \"sourceType\": \"POSTGRESQL\",\n" + " \"connectionType\": \"JDBC\",\n" + " \"connectionTypeCode\": \"GENERICUSER\",\n" + " \"connectionDriver\": \"org.postgresql.Driver\",\n" + " \"connectionString\": \"jdbc:postgresql://192.168.1.100:5432/testdata\",\n" + " \"connectionTimeout\": 180,\n" + " \"userName\": \"postgres\",\n" + " \"minimumConnections\": 1,\n" + " \"maximumConnections\": 5,\n" + " \"refreshTime\": 180,\n" + " \"timezone\": \"AUSTRALIA/SYDNEY\",\n" + " \"accessLevelCode\": \"UNSECURE\",\n" + " \"maxRows\": 10000,\n" + " \"maxAnalysisRows\": 0,\n" + " \"inheritChildSourceFilters\": false,\n" + " \"sourceLogIndicator\": false,\n" + " \"sourceOptions\": [\n" + "{\n" + "\"optionKey\": \"ISOLATIONLEVEL\",\n" + "\"optionValue\": \"1.0\",\n" + "\"valueDataType\": \"1\"\n" + "},\n" + "{\n" + "\"optionKey\": \"USESCHEMA\",\n" + "\"optionValue\": \"true\",\n" + "\"valueDataType\": \"6\"\n" + "},\n" + "{\n" + "\"optionKey\": \"HOSTNAME\",\n" + "\"optionValue\": \"192.168.1.100\",\n" + "\"valueDataType\": \"2\"\n" + "},\n" + "{\n" + "\"optionKey\": \"PORT\",\n" + "\"optionValue\": \"5432\",\n" + "\"valueDataType\": \"1\"\n" + "},\n" + "{\n" + "\"optionKey\": \"DATABASE\",\n" + "\"optionValue\": \"testdata\",\n" + "\"valueDataType\": \"2\"\n" + "},\n" + "{\n" + "\"optionKey\": \"YF_DRIVER_SELECTION\",\n" + "\"optionValue\": \"org.postgresql.Driver\",\n" + "\"valueDataType\": \"2\"\n" + "}\n" + " ]\n" + "}" ; String token = generateToken(host, restUsername, restPassword); System.out.println("Payload: " + createDataSourcePayload); Content c = Request.post(host + "/api/data-sources") .addHeader("Authorization", "YELLOWFIN ts=" + System.currentTimeMillis() + " , nonce=" + new Random().nextLong() + ", token=" + token) .addHeader("Accept", "application/vnd.yellowfin.api-v1+json") .addHeader("Content-Type", "application/json") .bodyString(createDataSourcePayload, null) .execute().returnContent(); System.out.print(c.asString()); } public static String generateToken(String host, String username, String password) throws IOException { Content c = Request.post(host + "/api/refresh-tokens") .addHeader("Authorization", "YELLOWFIN ts=" + System.currentTimeMillis() + " , nonce=" + new Random().nextLong()) .addHeader("Accept", "application/vnd.yellowfin.api-v1+json") .addHeader("Content-Type", "application/json") .bodyString("{ \"userName\": \""+ username + "\",\"password\": \""+ password + "\"}", null) .execute().returnContent(); JsonObject jsonObject = new JsonParser().parse(c.asString()).getAsJsonObject(); JsonElement accessToken = jsonObject.getAsJsonObject("_embedded").getAsJsonObject("accessToken").get("securityToken"); if (accessToken!=null) { System.out.println("Access Token: " + accessToken); } else { System.out.println("Token not retrieved successfully"); System.exit(-1); } return accessToken.getAsString(); } }
using System.Net.Http.Headers; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace YellowfinAPIExamples { public class CreateADataSource { static async Task Main(string[] args) { string host = "http://localhost:8080/Yellowfin"; string restUsername = "admin@yellowfin.com.au"; string restPassword = "test"; string createDataSourcePayload = @" { ""sourceName"": ""PostgreSQL Database Created Via Import"", ""sourceDescription"": """", ""sourceType"": ""POSTGRESQL"", ""connectionType"": ""JDBC"", ""connectionTypeCode"": ""GENERICUSER"", ""connectionDriver"": ""org.postgresql.Driver"", ""connectionString"": ""jdbc:postgresql://192.168.1.100:5432/testdata"", ""connectionTimeout"": 180, ""userName"": ""postgres"", ""minimumConnections"": 1, ""maximumConnections"": 5, ""refreshTime"": 180, ""timezone"": ""AUSTRALIA/SYDNEY"", ""accessLevelCode"": ""UNSECURE"", ""maxRows"": 10000, ""maxAnalysisRows"": 0, ""inheritChildSourceFilters"": false, ""sourceLogIndicator"": false, ""sourceOptions"": [ { ""optionKey"": "ISOLATIONLEVEL"", ""optionValue"": ""1.0"", ""valueDataType"": ""1"" }, { ""optionKey"": ""USESCHEMA"", ""optionValue"": ""true"", ""valueDataType"": ""6"" }, { ""optionKey"": ""HOSTNAME"", ""optionValue"": ""192.168.1.100"", ""valueDataType"": ""2"" }, { ""optionKey"": ""PORT"", ""optionValue"": ""5432"", ""valueDataType"": ""1"" }, { ""optionKey"": ""DATABASE"", ""optionValue"": ""testdata"", ""valueDataType"": ""2"" }, { ""optionKey"": ""YF_DRIVER_SELECTION"", ""optionValue"": ""org.postgresql.Driver"", ""valueDataType"": ""2"" } ] }"; string token = await GenerateToken(host, restUsername, restPassword); Console.WriteLine("Payload: " + createDataSourcePayload); using (var httpClient = new HttpClient()) { httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("YELLOWFIN", $"ts={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}, nonce={new Random().NextInt64()}, token={token}"); httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.yellowfin.api-v1+json")); var content = new StringContent(createDataSourcePayload, System.Text.Encoding.UTF8, "application/json"); HttpResponseMessage response = await httpClient.PostAsync($"{host}/api/data-sources", content); if (response.IsSuccessStatusCode) { string responseBody = await response.Content.ReadAsStringAsync(); Console.WriteLine(responseBody); } else { Console.WriteLine("Failed to create data source. Status code: " + response.StatusCode); } } } static async Task<string> GenerateToken(string host, string restUsername, string restPassword) { using (var client = new HttpClient()) { // Generate nonce long nonce = new Random().NextInt64(); // Create HTTP request var request = new HttpRequestMessage(HttpMethod.Post, $"{host}/api/refresh-tokens"); request.Headers.Add("Authorization", $"YELLOWFIN ts={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}, nonce={nonce}"); request.Headers.Add("Accept", "application/vnd.yellowfin.api-v1+json"); request.Content = new StringContent( JsonConvert.SerializeObject(new { userName = restUsername, password = restPassword }), System.Text.Encoding.UTF8, "application/json" ); // Send request and get response HttpResponseMessage response = await client.SendAsync(request); string responseContent = await response.Content.ReadAsStringAsync(); // Parse JSON response JObject jsonObject = JsonConvert.DeserializeObject<JObject>(responseContent); string accessToken = jsonObject["_embedded"]["accessToken"]["securityToken"].ToString(); if (!string.IsNullOrEmpty(accessToken)) { Console.WriteLine("Access Token: " + accessToken); } else { Console.WriteLine("Token not retrieved"); Environment.Exit(-1); } return accessToken; } } } }
package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "math/rand" "net/http" "time" ) func main() { host := "http://localhost:8080/Yellowfin" restUsername := "admin@yellowfin.com.au" restPassword := "test" createDataSourcePayload := `{ "sourceName": "PostgreSQL Database Created Via Import", "sourceDescription": "", "sourceType": "POSTGRESQL", "connectionType": "JDBC", "connectionTypeCode": "GENERICUSER", "connectionDriver": "org.postgresql.Driver", "connectionString": "jdbc:postgresql://192.168.1.100:5432/testdata", "connectionTimeout": 180, "userName": "postgres", "minimumConnections": 1, "maximumConnections": 5, "refreshTime": 180, "timezone": "AUSTRALIA/SYDNEY", "accessLevelCode": "UNSECURE", "maxRows": 10000, "maxAnalysisRows": 0, "inheritChildSourceFilters": false, "sourceLogIndicator": false, "sourceOptions": [ { "optionKey": "ISOLATIONLEVEL", "optionValue": "1.0", "valueDataType": "1" }, { "optionKey": "USESCHEMA", "optionValue": "true", "valueDataType": "6" }, { "optionKey": "HOSTNAME", "optionValue": "192.168.1.100", "valueDataType": "2" }, { "optionKey": "PORT", "optionValue": "5432", "valueDataType": "1" }, { "optionKey": "DATABASE", "optionValue": "testdata", "valueDataType": "2" }, { "optionKey": "YF_DRIVER_SELECTION", "optionValue": "org.postgresql.Driver", "valueDataType": "2" } ] }` token, err := generateToken(host, restUsername, restPassword) if err != nil { fmt.Println("Error generating token:", err) return } fmt.Println("Payload:", createDataSourcePayload) client := &http.Client{} req, err := http.NewRequest("POST", host+"/api/data-sources", bytes.NewBuffer([]byte(createDataSourcePayload))) if err != nil { fmt.Println("Error creating request:", err) return } nonce := rand.Int63() req.Header.Set("Authorization", fmt.Sprintf("YELLOWFIN ts=%d, nonce=%d, token=%s", time.Now().UnixMilli(), nonce, token)) req.Header.Set("Accept", "application/vnd.yellowfin.api-v1+json") req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response body:", err) return } fmt.Println(string(body)) } func generateToken(host, restUsername, restPassword string) (string, error) { nonce := rand.Int63() requestBody, err := json.Marshal(map[string]string{ "userName": restUsername, "password": restPassword, }) if err != nil { fmt.Println("Error marshaling request body:", err) return "", err } client := &http.Client{} req, err := http.NewRequest("POST", host+"/api/refresh-tokens", bytes.NewBuffer(requestBody)) if err != nil { fmt.Println("Error creating request:", err) return "", err } req.Header.Set("Authorization", fmt.Sprintf("YELLOWFIN ts=%d, nonce=%d", time.Now().UnixMilli(), nonce)) req.Header.Set("Accept", "application/vnd.yellowfin.api-v1+json") req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return "", err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response body:", err) return "", err } var jsonResponse map[string]interface{} err = json.Unmarshal(body, &jsonResponse) if err != nil { fmt.Println("Error parsing JSON response:", err) return "", err } accessToken, ok := jsonResponse["_embedded"].(map[string]interface{})["accessToken"].(map[string]interface{})["securityToken"].(string) if !ok { fmt.Println("Token not retrieved") return "", fmt.Errorf("Token not retrieved successfully") } return accessToken, nil }
const fetch = require("node-fetch"); async function main() { const host = "http://localhost:8080/Yellowfin"; const restUsername = "admin@yellowfin.com.au"; const restPassword = "test"; const createDataSourcePayload = `{ "sourceName": "PostgreSQL Database Created Via Import", "sourceDescription": "", "sourceType": "POSTGRESQL", "connectionType": "JDBC", "connectionTypeCode": "GENERICUSER", "connectionDriver": "org.postgresql.Driver", "connectionString": "jdbc:postgresql://192.168.1.100:5432/testdata", "connectionTimeout": 180, "userName": "postgres", "minimumConnections": 1, "maximumConnections": 5, "refreshTime": 180, "timezone": "AUSTRALIA/SYDNEY", "accessLevelCode": "UNSECURE", "maxRows": 10000, "maxAnalysisRows": 0, "inheritChildSourceFilters": false, "sourceLogIndicator": false, "sourceOptions": [ { "optionKey": "ISOLATIONLEVEL", "optionValue": "1.0", "valueDataType": "1" }, { "optionKey": "USESCHEMA", "optionValue": "true", "valueDataType": "6" }, { "optionKey": "HOSTNAME", "optionValue": "192.168.1.100", "valueDataType": "2" }, { "optionKey": "PORT", "optionValue": "5432", "valueDataType": "1" }, { "optionKey": "DATABASE", "optionValue": "testdata", "valueDataType": "2" }, { "optionKey": "YF_DRIVER_SELECTION", "optionValue": "org.postgresql.Driver", "valueDataType": "2" } ] }`; const token = await generateToken(host, restUsername, restPassword); if (!token) { console.error("Failed to retrieve access token"); return; } console.log("Payload:", createDataSourcePayload); const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); const headers = { 'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}, token=${token}`, 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' }; try { const response = await fetch(`${host}/api/data-sources`, { method: 'POST', headers: headers, body: createDataSourcePayload }); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const responseBody = await response.text(); console.log(responseBody); } catch (error) { console.error("Error:", error.message); } } async function generateToken(host, restUsername, restPassword) { const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); const headers = { 'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}`, 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' }; const body = JSON.stringify({ userName: restUsername, password: restPassword }); try { const response = await fetch(`${host}/api/refresh-tokens`, { method: 'POST', headers: headers, body: body }); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const jsonResponse = await response.json(); const accessToken = jsonResponse._embedded.accessToken.securityToken; if (accessToken) { console.log(`Access Token: ${accessToken}`); } else { console.log("Token not retrieved"); } return accessToken; } catch (error) { console.error("Error:", error.message); } return null; } main();
<?php function main() { $host = "http://localhost:8080/Yellowfin"; $restUsername = "admin@yellowfin.com.au"; $restPassword = "test"; $createDataSourcePayload = '{ "sourceName": "PostgreSQL Database Created Via Import", "sourceDescription": "", "sourceType": "POSTGRESQL", "connectionType": "JDBC", "connectionTypeCode": "GENERICUSER", "connectionDriver": "org.postgresql.Driver", "connectionString": "jdbc:postgresql://192.168.1.100:5432/testdata", "connectionTimeout": 180, "userName": "postgres", "minimumConnections": 1, "maximumConnections": 5, "refreshTime": 180, "timezone": "AUSTRALIA/SYDNEY", "accessLevelCode": "UNSECURE", "maxRows": 10000, "maxAnalysisRows": 0, "inheritChildSourceFilters": false, "sourceLogIndicator": false, "sourceOptions": [ { "optionKey": "ISOLATIONLEVEL", "optionValue": "1.0", "valueDataType": "1" }, { "optionKey": "USESCHEMA", "optionValue": "true", "valueDataType": "6" }, { "optionKey": "HOSTNAME", "optionValue": "192.168.1.100", "valueDataType": "2" }, { "optionKey": "PORT", "optionValue": "5432", "valueDataType": "1" }, { "optionKey": "DATABASE", "optionValue": "testdata", "valueDataType": "2" }, { "optionKey": "YF_DRIVER_SELECTION", "optionValue": "org.postgresql.Driver", "valueDataType": "2" } ] }'; try { $token = generateToken($host, $restUsername, $restPassword); } catch (Exception $e) { echo "Error generating token: " . $e->getMessage(); return; } echo "Payload: " . $createDataSourcePayload . "\n"; $nonce = mt_rand(); $headers = array( 'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . $nonce . ', token=' . $token, 'Accept: application/vnd.yellowfin.api-v1+json', 'Content-Type: application/json' ); try { $response = httpRequest('POST', "$host/api/data-sources", $headers, $createDataSourcePayload); echo $response; } catch (Exception $e) { echo "Error sending request: " . $e->getMessage(); } } function generateToken($host, $restUsername, $restPassword) { // Generate nonce $nonce = mt_rand(); // Create request body $requestBody = json_encode(array( "userName" => $restUsername, "password" => $restPassword )); // Create request headers $headers = array( 'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . $nonce, 'Accept: application/vnd.yellowfin.api-v1+json', 'Content-Type: application/json' ); $response = httpRequest('POST', "$host/api/refresh-tokens", $headers, $requestBody); // Parse JSON response $jsonResponse = json_decode($response, true); // Get access token from response if (isset($jsonResponse["_embedded"]["accessToken"]["securityToken"])) { $accessToken = $jsonResponse["_embedded"]["accessToken"]["securityToken"]; echo "Access Token: " . $accessToken; return $accessToken; } else { throw new Exception("Token not retrieved successfully"); } } function httpRequest($method, $url, $headers, $data = null) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); if ($data !== null) { curl_setopt($ch, CURLOPT_POSTFIELDS, $data); } $response = curl_exec($ch); if (curl_errno($ch)) { throw new Exception('Error: ' . curl_error($ch)); } curl_close($ch); return $response; } main(); ?>
import json import random import time import requests def main(): host = "http://localhost:8080/Yellowfin" rest_username = "admin@yellowfin.com.au" rest_password = "test" create_data_source_payload = ''' { "sourceName": "PostgreSQL Database Created Via Import", "sourceDescription": "", "sourceType": "POSTGRESQL", "connectionType": "JDBC", "connectionTypeCode": "GENERICUSER", "connectionDriver": "org.postgresql.Driver", "connectionString": "jdbc:postgresql://192.168.1.100:5432/testdata", "connectionTimeout": 180, "userName": "postgres", "minimumConnections": 1, "maximumConnections": 5, "refreshTime": 180, "timezone": "AUSTRALIA/SYDNEY", "accessLevelCode": "UNSECURE", "maxRows": 10000, "maxAnalysisRows": 0, "inheritChildSourceFilters": false, "sourceLogIndicator": false, "sourceOptions": [ { "optionKey": "ISOLATIONLEVEL", "optionValue": "1.0", "valueDataType": "1" }, { "optionKey": "USESCHEMA", "optionValue": "true", "valueDataType": "6" }, { "optionKey": "HOSTNAME", "optionValue": "192.168.1.100", "valueDataType": "2" }, { "optionKey": "PORT", "optionValue": "5432", "valueDataType": "1" }, { "optionKey": "DATABASE", "optionValue": "testdata", "valueDataType": "2" }, { "optionKey": "YF_DRIVER_SELECTION", "optionValue": "org.postgresql.Driver", "valueDataType": "2" } ] } ''' try: token = generate_token(host, rest_username, rest_password) except Exception as e: print(f"Error generating token: {e}") return print("Payload:", create_data_source_payload) nonce = random.randint(0, 2**63 - 1) headers = { 'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={nonce}, token={token}', 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' } try: response = requests.post(f"{host}/api/data-sources", headers=headers, data=create_data_source_payload) response.raise_for_status() print(response.text) except requests.RequestException as e: print(f"Error sending request: {e}") def generate_token(host, rest_username, rest_password): nonce = random.randint(0, 2**63 - 1) # Create request body request_body = json.dumps({ "userName": rest_username, "password": rest_password }) # Create request headers headers = { 'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={nonce}', 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' } try: response = requests.post(f"{host}/api/refresh-tokens", headers=headers, data=request_body) response.raise_for_status() json_response = response.json() access_token = json_response["_embedded"]["accessToken"]["securityToken"] print("Access Token:", access_token) return access_token except requests.RequestException as e: raise Exception("Token not retrieved successfully") from e if __name__ == "__main__": main()
データソースの一覧化
データソースの一覧は、GET /api/data-sources エンドポイント Get All Data Sources を使用することで取得できます。これは、以下の形式のデータソースモデルを返します。
{ "sourceId": 132780, "sourceName": "PostgreSQL Connection for NEWCLIENT", "sourceDescription": "PostgreSQL Connection for NEWCLIENT", "sourceType": "POSTGRESQL", "connectionType": "JDBC", "connectionTypeCode": "GENERICUSER", "connectionDriver": "org.postgresql.Driver", "connectionPath": "public", "connectionString": "jdbc:postgresql://localhost:5432/testdata", "connectionTimeout": 180, "userName": "postgres", "minimumConnections": 1, "maximumConnections": 5, "refreshTime": 180, "timezone": "AUSTRALIA/LORD_HOWE", "accessLevelCode": "UNSECURE", "maxRows": 10000, "maxAnalysisRows": 0, "inheritChildSourceFilters": false, "sourceLogIndicator": false }
こちらのサービスを使用して、指定されたデータソース名のデータソースの内部整数識別子 (sourceId) を検索できます。
以下のコード例は、システムからデータソースの一覧を取得する方法を示しています。
package rest.code.examples; import java.io.IOException; import java.util.Random; import org.apache.hc.client5.http.fluent.Content; import org.apache.hc.client5.http.fluent.Request; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; /** * List DataSources using the Yellowfin REST API */ public class ListDataSources { public static void main(String[] args) throws Exception { System.out.print("List Datasources"); String host = "http://localhost:8080/Yellowfin"; String restUsername = "admin@yellowfin.com.au"; String restPassword = "test"; String token = generateToken(host, restUsername, restPassword); Content c = Request.get(host + "/api/data-sources") .addHeader("Authorization", "YELLOWFIN ts=" + System.currentTimeMillis() + " , nonce=" + new Random().nextLong() + ", token=" + token) .addHeader("Accept", "application/vnd.yellowfin.api-v1+json") .addHeader("Content-Type", "application/json") .execute().returnContent(); System.out.print(c.asString()); } /* * This function generates an access token for a user that will grant them access to * call REST API endpoints. */ public static String generateToken(String host, String username, String password) throws IOException { Content c = Request.post(host + "/api/refresh-tokens") .addHeader("Authorization", "YELLOWFIN ts=" + System.currentTimeMillis() + " , nonce=" + new Random().nextLong()) .addHeader("Accept", "application/vnd.yellowfin.api-v1+json") .addHeader("Content-Type", "application/json") .bodyString("{ \"userName\": \""+ username + "\",\"password\": \""+ password + "\"}", null) .execute().returnContent(); JsonObject jsonObject = new JsonParser().parse(c.asString()).getAsJsonObject(); JsonElement accessToken = jsonObject.getAsJsonObject("_embedded").getAsJsonObject("accessToken").get("securityToken"); if (accessToken!=null) { System.out.println("Access Token: " + accessToken); } else { System.out.println("Token not retrieved successfully"); System.exit(-1); } return accessToken.getAsString(); } }
using System.Net.Http.Headers; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace YellowfinAPIExamples { public class ListDataSources { static async Task Main(string[] args) { string host = "http://localhost:8080/Yellowfin"; string restUsername = "admin@yellowfin.com.au"; string restPassword = "test"; string token = await GenerateToken(host, restUsername, restPassword); Console.WriteLine("List Datasources"); using (var httpClient = new HttpClient()) { long nonce = new Random().NextInt64(); // Setup request headers httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("YELLOWFIN", $"ts={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}, nonce={nonce}, token={token}"); httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.yellowfin.api-v1+json")); // Make GET request to retrieve data sources HttpResponseMessage response = await httpClient.GetAsync($"{host}/api/data-sources"); if (response.IsSuccessStatusCode) { string responseBody = await response.Content.ReadAsStringAsync(); Console.WriteLine(responseBody); } else { Console.WriteLine($"Failed to retrieve data sources. Status code: {response.StatusCode}"); } } } static async Task<string> GenerateToken(string host, string username, string password) { using (var client = new HttpClient()) { // Generate nonce long nonce = new Random().NextInt64(); // Create HTTP request var request = new HttpRequestMessage(HttpMethod.Post, $"{host}/api/refresh-tokens"); request.Headers.Authorization = new AuthenticationHeaderValue("YELLOWFIN", $"ts={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}, nonce={nonce}"); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.yellowfin.api-v1+json")); request.Content = new StringContent( JsonConvert.SerializeObject(new { userName = username, password = password }), System.Text.Encoding.UTF8, "application/json" ); // Send request and get response HttpResponseMessage response = await client.SendAsync(request); string responseContent = await response.Content.ReadAsStringAsync(); // Parse JSON response JObject jsonObject = JsonConvert.DeserializeObject<JObject>(responseContent); string accessToken = jsonObject["_embedded"]["accessToken"]["securityToken"].ToString(); if (!string.IsNullOrEmpty(accessToken)) { Console.WriteLine("Access Token: " + accessToken); } else { Console.WriteLine("Token not retrieved successfully"); Environment.Exit(-1); } return accessToken; } } } }
package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "math/rand" "net/http" "time" ) func main() { host := "http://localhost:8080/Yellowfin" restUsername := "admin@yellowfin.com.au" restPassword := "test" token, err := generateToken(host, restUsername, restPassword) if err != nil { fmt.Println("Error generating token:", err) return } fmt.Println("List Datasources") client := &http.Client{} req, err := http.NewRequest("GET", host+"/api/data-sources", nil) if err != nil { fmt.Println("Error creating request:", err) return } nonce := rand.Int63() req.Header.Set("Authorization", fmt.Sprintf("YELLOWFIN ts=%d, nonce=%d, token=%s", time.Now().UnixMilli(), nonce, token)) req.Header.Set("Accept", "application/vnd.yellowfin.api-v1+json") req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response body:", err) return } fmt.Println(string(body)) } func generateToken(host, username, password string) (string, error) { // Generate nonce nonce := rand.Int63() // Create request body requestBody, err := json.Marshal(map[string]string{ "userName": username, "password": password, }) if err != nil { fmt.Println("Error marshaling request body:", err) return "", err } // Create HTTP client client := &http.Client{} // Create HTTP request request, err := http.NewRequest("POST", host+"/api/refresh-tokens", bytes.NewBuffer(requestBody)) if err != nil { fmt.Println("Error creating request:", err) return "", err } // Add request headers request.Header.Set("Authorization", fmt.Sprintf("YELLOWFIN ts=%d, nonce=%d", time.Now().UnixMilli(), nonce)) request.Header.Set("Accept", "application/vnd.yellowfin.api-v1+json") request.Header.Set("Content-Type", "application/json") // Send HTTP request response, err := client.Do(request) if err != nil { fmt.Println("Error sending request:", err) return "", err } defer response.Body.Close() // Read response body responseBody, err := ioutil.ReadAll(response.Body) if err != nil { fmt.Println("Error reading response body:", err) return "", err } // Parse JSON response var jsonResponse map[string]interface{} err = json.Unmarshal(responseBody, &jsonResponse) if err != nil { fmt.Println("Error parsing JSON response:", err) return "", err } // Get access token from response accessToken, ok := jsonResponse["_embedded"].(map[string]interface{})["accessToken"].(map[string]interface{})["securityToken"].(string) if !ok { fmt.Println("Token not retrieved") return "", fmt.Errorf("Token not retrieved successfully") } return accessToken, nil }
const fetch = require("node-fetch"); async function main() { const host = "http://localhost:8080/Yellowfin"; const restUsername = "admin@yellowfin.com.au"; const restPassword = "test"; const createUserPayload = JSON.stringify([{ userId: "user1", emailAddress: "user1@yellowfin.com.au", roleCode: "Consumer & Collaborator", password: "test", firstName: "User", lastName: "One", languageCode: "EN", timeZoneCode: "AUSTRALIA/SYDNEY" }]); const token = await generateToken(host, restUsername, restPassword); if (!token) { console.error("Failed to retrieve access token"); return; } console.log("Payload:", createUserPayload); const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); const headers = { 'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}, token=${token}`, 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' }; try { const response = await fetch(`${host}/api/data-sources`, { method: 'GET', headers: headers }); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const responseBody = await response.text(); console.log(responseBody); } catch (error) { console.error("Error:", error.message); } } async function generateToken(host, restUsername, restPassword) { // Generate nonce const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); // Create request headers const headers = { 'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}`, 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' }; // Create request body const body = JSON.stringify({ userName: restUsername, password: restPassword }); try { // Make POST request const response = await fetch(`${host}/api/refresh-tokens`, { method: 'POST', headers: headers, body: body }); // Check if request was successful if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } // Parse JSON response const jsonResponse = await response.json(); const accessToken = jsonResponse._embedded.accessToken.securityToken; if (accessToken) { console.log(`Access Token: ${accessToken}`); } else { console.log("Token not retrieved"); } return accessToken; } catch (error) { console.error("Error:", error.message); } return null; } main();
<?php function main() { $host = "http://localhost:8080/Yellowfin"; $restUsername = "admin@yellowfin.com.au"; $restPassword = "test"; $createUserPayload = json_encode(array( array( "userId" => "user1", "emailAddress" => "user1@yellowfin.com.au", "roleCode" => "Consumer & Collaborator", "password" => "test", "firstName" => "User", "lastName" => "One", "languageCode" => "EN", "timeZoneCode" => "AUSTRALIA/SYDNEY" ) )); try { $token = generateToken($host, $restUsername, $restPassword); } catch (Exception $e) { echo "Error generating token: " . $e->getMessage(); return; } echo "Payload: " . $createUserPayload . "\n"; $nonce = mt_rand(); $headers = array( 'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . $nonce . ', token=' . $token, 'Accept: application/vnd.yellowfin.api-v1+json', 'Content-Type: application/json' ); try { $response = httpRequest('GET', "$host/api/data-sources", $headers); echo $response; } catch (Exception $e) { echo "Error listing data sources: " . $e->getMessage(); } } function generateToken($host, $restUsername, $restPassword) { // Generate nonce $nonce = mt_rand(); // Create request body $requestBody = json_encode(array( "userName" => $restUsername, "password" => $restPassword )); // Create request headers $headers = array( 'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . $nonce, 'Accept: application/vnd.yellowfin.api-v1+json', 'Content-Type: application/json' ); $response = httpRequest('POST', "$host/api/refresh-tokens", $headers, $requestBody); // Parse JSON response $jsonResponse = json_decode($response, true); // Get access token from response if (isset($jsonResponse["_embedded"]["accessToken"]["securityToken"])) { $accessToken = $jsonResponse["_embedded"]["accessToken"]["securityToken"]; echo "Access Token: " . $accessToken; return $accessToken; } else { throw new Exception("Token not retrieved successfully"); } } function httpRequest($method, $url, $headers, $data = null) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); if ($data !== null) { curl_setopt($ch, CURLOPT_POSTFIELDS, $data); } $response = curl_exec($ch); if (curl_errno($ch)) { throw new Exception('Error: ' . curl_error($ch)); } curl_close($ch); return $response; } main(); ?>
import json import random import time import requests def main(): host = "http://localhost:8080/Yellowfin" rest_username = "admin@yellowfin.com.au" rest_password = "test" try: token = generate_token(host, rest_username, rest_password) list_data_sources(host, token) except Exception as e: print(f"Error: {e}") def list_data_sources(host, token): headers = { 'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={random.randint(0, 2**63 - 1)}, token={token}', 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' } try: response = requests.get(f'{host}/api/data-sources', headers=headers) response.raise_for_status() print(response.text) except requests.RequestException as e: print(f"Error listing data sources: {e}") def generate_token(host, username, password): nonce = random.randint(0, 2 ** 63 - 1) request_body = json.dumps({ "userName": username, "password": password }) headers = { 'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={nonce}', 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' } try: response = requests.post(f'{host}/api/refresh-tokens', headers=headers, data=request_body) response.raise_for_status() json_response = response.json() access_token = json_response["_embedded"]["accessToken"]["securityToken"] print("Access Token:", access_token) return access_token except requests.RequestException as e: print(f"Token retrieval error: {e}") raise Exception("Token not retrieved successfully") if __name__ == "__main__": main()
ソース置換のためのクライアントデータソースのプライマリー組織データソースへの添付
クライアントデータソースは、POST /api/data-sources/{primaryOrgSourceId}/client-data-sources/?clientSourceId={clientOrgSourceId} エンドポイント Add Client Data Source を使用して、(ソース置換で使用するために) プライマリー組織データソースにリンクできます。
ここで、{primaryOrgSourceId} は、プライマリー組織データソースの整数識別子であり、{clientOrgSourceId} は、リンクするクライアント組織データソースの整数識別子です。
以下の例では、(名前で識別された) クライアントデータソースを、(名前で識別された) プライマリー組織データソースにリンクする方法を示しています。
package rest.code.examples; import java.io.IOException; import java.util.Random; import org.apache.hc.client5.http.fluent.Content; import org.apache.hc.client5.http.fluent.Request; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; /** * Attach a Client Datasource to Primary Org Source for Source Substitution using the Yellowfin REST API */ public class AttachClientDatasourceToPrimarySource { public static void main(String[] args) throws Exception { System.out.print("Attach a Tenant Source to Primary Org Source for Source Substitution"); String host = "http://localhost:8080/Yellowfin"; String restUsername = "admin@yellowfin.com.au"; String restPassword = "test"; String primarySourceName = "PostgreSQL Connection at Primary Org"; String clientSourceName = "PostgreSQL Connection for NEWCLIENT"; String clientOrgReference = "NEWCLIENT"; String clientToken = generateToken(host, restUsername, restPassword, clientOrgReference); Integer clientOrgSourceId = findDataSourceForSourceNameAtClient(host, clientToken, clientSourceName); System.out.println("Client Org Source Id: " + clientOrgSourceId); String primaryToken = generateToken(host, restUsername, restPassword, null); Integer primaryOrgSourceId = findDataSourceForSourceNameAtClient(host, primaryToken, primarySourceName); System.out.println("Primary Org Source Id: " + clientOrgSourceId); Content c = Request.get(host + "/api/data-sources/" + primaryOrgSourceId + "/client-data-sources/?clientSourceId=" + clientOrgSourceId) .addHeader("Authorization", "YELLOWFIN ts=" + System.currentTimeMillis() + " , nonce=" + new Random().nextLong() + ", token=" + primaryToken) .addHeader("Accept", "application/vnd.yellowfin.api-v1+json") .addHeader("Content-Type", "application/json") .execute().returnContent(); System.out.print(c.asString()); } /* * This function finds a datasource for a given datasource name * call REST API endpoints. */ private static Integer findDataSourceForSourceNameAtClient(String host, String token, String sourceName) throws IOException { Content c = Request.get(host + "/api/data-sources") .addHeader("Authorization", "YELLOWFIN ts=" + System.currentTimeMillis() + " , nonce=" + new Random().nextLong() + ", token=" + token) .addHeader("Accept", "application/vnd.yellowfin.api-v1+json") .addHeader("Content-Type", "application/json") .execute().returnContent(); JsonObject jsonObject = new JsonParser().parse(c.asString()).getAsJsonObject(); JsonElement sourceList = jsonObject.get("items"); JsonArray sources = sourceList.getAsJsonArray(); for (int i=0; i < sources.size(); i++ ) { JsonObject source = sources.getAsJsonArray().get(i).getAsJsonObject(); if (sourceName.equals(source.get("sourceName").getAsString())) return source.get("sourceId").getAsInt(); } System.out.println("Data Source could not be found for name:" + sourceName); System.exit(-1); return null; } /* * This function generates an access token for a user that will grant them access to * call REST API endpoints. */ public static String generateToken(String host, String username, String password, String tenantClientOrgRefId) throws IOException { String tokenBody = "{ \"userName\": \""+ username + "\",\"password\": \""+ password + "\""; if (tenantClientOrgRefId!=null) { tokenBody = tokenBody + ",\"clientOrgRef\": \""+ tenantClientOrgRefId + "\""; } tokenBody = tokenBody + "}"; Content c = Request.post(host + "/api/refresh-tokens") .addHeader("Authorization", "YELLOWFIN ts=" + System.currentTimeMillis() + " , nonce=" + new Random().nextLong()) .addHeader("Accept", "application/vnd.yellowfin.api-v1+json") .addHeader("Content-Type", "application/json") .bodyString(tokenBody, null) .execute().returnContent(); JsonObject jsonObject = new JsonParser().parse(c.asString()).getAsJsonObject(); JsonElement accessToken = jsonObject.getAsJsonObject("_embedded").getAsJsonObject("accessToken").get("securityToken"); if (accessToken!=null) { System.out.println("Access Token: " + accessToken); } else { System.out.println("Token not retrieved successfully"); System.exit(-1); } return accessToken.getAsString(); } }
using System.Net.Http.Headers; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace YellowfinAPIExamples { public class AttachClientDatasourceToPrimarySource { static async Task Main(string[] args) { Console.WriteLine("Attach a Tenant Source to Primary Org Source for Source Substitution"); string host = "http://localhost:8080/Yellowfin"; string restUsername = "admin@yellowfin.com.au"; string restPassword = "test"; string primarySourceName = "PostgreSQL Connection at Primary Org"; string clientSourceName = "PostgreSQL Connection for NEWCLIENT"; string clientOrgReference = "NEWCLIENT"; string clientToken = await GenerateToken(host, restUsername, restPassword, clientOrgReference); int clientOrgSourceId = await FindDataSourceForSourceNameAtClient(host, clientToken, clientSourceName); Console.WriteLine("Client Org Source Id: " + clientOrgSourceId); string primaryToken = await GenerateToken(host, restUsername, restPassword, null); int primaryOrgSourceId = await FindDataSourceForSourceNameAtClient(host, primaryToken, primarySourceName); Console.WriteLine("Primary Org Source Id: " + primaryOrgSourceId); using (var httpClient = new HttpClient()) { long nonce = new Random().NextInt64(); // Setup request headers httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("YELLOWFIN", $"ts={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}, nonce={nonce}, token={primaryToken}"); httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.yellowfin.api-v1+json")); // Make GET request to attach client datasource to primary org source HttpResponseMessage response = await httpClient.GetAsync($"{host}/api/data-sources/{primaryOrgSourceId}/client-data-sources/?clientSourceId={clientOrgSourceId}"); if (response.IsSuccessStatusCode) { string responseBody = await response.Content.ReadAsStringAsync(); Console.WriteLine(responseBody); } else { Console.WriteLine($"Failed to attach client datasource. Status code: {response.StatusCode}"); } } } static async Task<int> FindDataSourceForSourceNameAtClient(string host, string token, string sourceName) { using (var httpClient = new HttpClient()) { // Setup request headers httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("YELLOWFIN", $"ts={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}, nonce={new Random().NextInt64()}, token={token}"); httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.yellowfin.api-v1+json")); // Make GET request to fetch data sources HttpResponseMessage response = await httpClient.GetAsync($"{host}/api/data-sources"); if (response.IsSuccessStatusCode) { string responseBody = await response.Content.ReadAsStringAsync(); // Parse JSON response JObject jsonObject = JsonConvert.DeserializeObject<JObject>(responseBody); JArray sources = jsonObject["items"].ToObject<JArray>(); // Iterate through sources to find the correct one foreach (JObject source in sources) { if (sourceName.Equals(source["sourceName"].ToString(), StringComparison.OrdinalIgnoreCase)) { return source["sourceId"].ToObject<int>(); } } } Console.WriteLine($"Data Source could not be found for name: {sourceName}"); Environment.Exit(-1); return -1; // Ideally unreachable, since Environment.Exit should terminate the process } } static async Task<string> GenerateToken(string host, string username, string password, string tenantClientOrgRefId) { using (var client = new HttpClient()) { // Generate nonce long nonce = new Random().NextInt64(); // Create HTTP request var request = new HttpRequestMessage(HttpMethod.Post, $"{host}/api/refresh-tokens"); request.Headers.Add("Authorization", $"YELLOWFIN ts={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}, nonce={nonce}"); request.Headers.Add("Accept", "application/vnd.yellowfin.api-v1+json"); request.Content = new StringContent( JsonConvert.SerializeObject(new { userName = username, password = password, clientOrgRef = tenantClientOrgRefId }), System.Text.Encoding.UTF8, "application/json" ); // Send request and get response HttpResponseMessage response = await client.SendAsync(request); string responseContent = await response.Content.ReadAsStringAsync(); // Parse JSON response JObject jsonObject = JsonConvert.DeserializeObject<JObject>(responseContent); string accessToken = jsonObject["_embedded"]["accessToken"]["securityToken"].ToString(); if (!string.IsNullOrEmpty(accessToken)) { Console.WriteLine("Access Token: " + accessToken); } else { Console.WriteLine("Token not retrieved successfully"); Environment.Exit(-1); } return accessToken; } } } }
package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "math/rand" "net/http" "time" ) func main() { fmt.Println("Attach a Tenant Source to Primary Org Source for Source Substitution") host := "http://localhost:8080/Yellowfin" restUsername := "admin@yellowfin.com.au" restPassword := "test" primarySourceName := "PostgreSQL Connection at Primary Org" clientSourceName := "PostgreSQL Connection for NEWCLIENT" clientOrgReference := "NEWCLIENT" clientToken, err := generateToken(host, restUsername, restPassword, clientOrgReference) if err != nil { fmt.Println("Error generating client token:", err) return } clientOrgSourceId, err := findDataSourceForSourceNameAtClient(host, clientToken, clientSourceName) if err != nil { fmt.Println("Error finding client data source:", err) return } fmt.Println("Client Org Source Id:", clientOrgSourceId) primaryToken, err := generateToken(host, restUsername, restPassword, "") if err != nil { fmt.Println("Error generating primary token:", err) return } primaryOrgSourceId, err := findDataSourceForSourceNameAtClient(host, primaryToken, primarySourceName) if err != nil { fmt.Println("Error finding primary data source:", err) return } fmt.Println("Primary Org Source Id:", primaryOrgSourceId) client := &http.Client{} nonce := rand.Int63() req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/data-sources/%d/client-data-sources/?clientSourceId=%d", host, primaryOrgSourceId, clientOrgSourceId), nil) if err != nil { fmt.Println("Error creating request:", err) return } req.Header.Set("Authorization", fmt.Sprintf("YELLOWFIN ts=%d, nonce=%d, token=%s", time.Now().UnixMilli(), nonce, primaryToken)) req.Header.Set("Accept", "application/vnd.yellowfin.api-v1+json") req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response body:", err) return } fmt.Println(string(body)) } func findDataSourceForSourceNameAtClient(host, token, sourceName string) (int, error) { client := &http.Client{} nonce := rand.Int63() req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/data-sources", host), nil) if err != nil { return 0, fmt.Errorf("Error creating request: %v", err) } req.Header.Set("Authorization", fmt.Sprintf("YELLOWFIN ts=%d, nonce=%d, token=%s", time.Now().UnixMilli(), nonce, token)) req.Header.Set("Accept", "application/vnd.yellowfin.api-v1+json") req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { return 0, fmt.Errorf("Error sending request: %v", err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return 0, fmt.Errorf("Error reading response body: %v", err) } var jsonResponse map[string]interface{} err = json.Unmarshal(body, &jsonResponse) if err != nil { return 0, fmt.Errorf("Error parsing JSON response: %v", err) } items := jsonResponse["items"].([]interface{}) for _, item := range items { source := item.(map[string]interface{}) if sourceName == source["sourceName"].(string) { sourceId := int(source["sourceId"].(float64)) return sourceId, nil } } return 0, fmt.Errorf("Data Source could not be found for name: %s", sourceName) } func generateToken(host, username, password, tenantClientOrgRefId string) (string, error) { nonce := rand.Int63() tokenBody := map[string]string{ "userName": username, "password": password, } if tenantClientOrgRefId != "" { tokenBody["clientOrgRef"] = tenantClientOrgRefId } requestBody, err := json.Marshal(tokenBody) if err != nil { return "", fmt.Errorf("Error marshaling request body: %v", err) } client := &http.Client{} req, err := http.NewRequest("POST", fmt.Sprintf("%s/api/refresh-tokens", host), bytes.NewBuffer(requestBody)) if err != nil { return "", fmt.Errorf("Error creating request: %v", err) } req.Header.Set("Authorization", fmt.Sprintf("YELLOWFIN ts=%d, nonce=%d", time.Now().UnixMilli(), nonce)) req.Header.Set("Accept", "application/vnd.yellowfin.api-v1+json") req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { return "", fmt.Errorf("Error sending request: %v", err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return "", fmt.Errorf("Error reading response body: %v", err) } var jsonResponse map[string]interface{} err = json.Unmarshal(body, &jsonResponse) if err != nil { return "", fmt.Errorf("Error parsing JSON response: %v", err) } embedded := jsonResponse["_embedded"].(map[string]interface{}) accessToken := embedded["accessToken"].(map[string]interface{})["securityToken"].(string) if accessToken == "" { return "", fmt.Errorf("Token not retrieved successfully") } fmt.Println("Access Token:", accessToken) return accessToken, nil }
const fetch = require("node-fetch"); async function main() { console.log("Attach a Tenant Source to Primary Org Source for Source Substitution"); const host = "http://localhost:8080/Yellowfin"; const restUsername = "admin@yellowfin.com.au"; const restPassword = "test"; const primarySourceName = "PostgreSQL Connection at Primary Org"; const clientSourceName = "PostgreSQL Connection for NEWCLIENT"; const clientOrgReference = "NEWCLIENT"; const clientToken = await generateToken(host, restUsername, restPassword, clientOrgReference); const clientOrgSourceId = await findDataSourceForSourceNameAtClient(host, clientToken, clientSourceName); console.log("Client Org Source Id:", clientOrgSourceId); const primaryToken = await generateToken(host, restUsername, restPassword, null); const primaryOrgSourceId = await findDataSourceForSourceNameAtClient(host, primaryToken, primarySourceName); console.log("Primary Org Source Id:", primaryOrgSourceId); const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); const headers = { 'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}, token=${primaryToken}`, 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' }; try { const response = await fetch(`${host}/api/data-sources/${primaryOrgSourceId}/client-data-sources/?clientSourceId=${clientOrgSourceId}`, { method: 'GET', headers: headers }); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const responseBody = await response.text(); console.log(responseBody); } catch (error) { console.error("Error:", error.message); } } async function findDataSourceForSourceNameAtClient(host, token, sourceName) { const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); const headers = { 'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}, token=${token}`, 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' }; try { const response = await fetch(`${host}/api/data-sources`, { method: 'GET', headers: headers }); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const jsonResponse = await response.json(); const sources = jsonResponse.items; for (let i = 0; i < sources.length; i++) { const source = sources[i]; if (sourceName === source.sourceName) { return source.sourceId; } } console.log("Data Source could not be found for name:", sourceName); process.exit(-1); // Exit if data source not found } catch (error) { console.error("Error:", error.message); process.exit(-1); // Exit on error } } async function generateToken(host, username, password, tenantClientOrgRefId) { const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); const headers = { 'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}`, 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' }; const requestBody = { userName: username, password: password }; if (tenantClientOrgRefId !== null) { requestBody.clientOrgRef = tenantClientOrgRefId; } try { const response = await fetch(`${host}/api/refresh-tokens`, { method: 'POST', headers: headers, body: JSON.stringify(requestBody) }); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const jsonResponse = await response.json(); const accessToken = jsonResponse._embedded.accessToken.securityToken; if (accessToken) { console.log(`Access Token: ${accessToken}`); } else { console.log("Token not retrieved successfully"); process.exit(-1); // Exit if token not retrieved } return accessToken; } catch (error) { console.error("Error:", error.message); process.exit(-1); // Exit on error } } main();
<?php function main() { $host = "http://localhost:8080/Yellowfin"; $restUsername = "admin@yellowfin.com.au"; $restPassword = "test"; echo "Attach a Tenant Source to Primary Org Source for Source Substitution\n"; $primarySourceName = "PostgreSQL Connection at Primary Org"; $clientSourceName = "PostgreSQL Connection for NEWCLIENT"; $clientOrgReference = "NEWCLIENT"; try { $clientToken = generateToken($host, $restUsername, $restPassword, $clientOrgReference); $clientOrgSourceId = findDataSourceForSourceNameAtClient($host, $clientToken, $clientSourceName); echo "Client Org Source Id: $clientOrgSourceId\n"; $primaryToken = generateToken($host, $restUsername, $restPassword, null); $primaryOrgSourceId = findDataSourceForSourceNameAtClient($host, $primaryToken, $primarySourceName); echo "Primary Org Source Id: $primaryOrgSourceId\n"; $headers = [ 'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . mt_rand() . ', token=' . $primaryToken, 'Accept: application/vnd.yellowfin.api-v1+json', 'Content-Type: application/json' ]; $url = "$host/api/data-sources/$primaryOrgSourceId/client-data-sources/?clientSourceId=$clientOrgSourceId"; $response = httpRequest('GET', $url, $headers); echo $response; } catch (Exception $e) { echo "Error: " . $e->getMessage(); } } function generateToken($host, $restUsername, $restPassword, $tenantClientOrgRefId = null) { $nonce = mt_rand(); $tokenBody = "{ \"userName\": \"$restUsername\", \"password\": \"$restPassword\""; if ($tenantClientOrgRefId !== null) { $tokenBody .= ", \"clientOrgRef\": \"$tenantClientOrgRefId\""; } $tokenBody .= "}"; $headers = [ 'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . $nonce, 'Accept: application/vnd.yellowfin.api-v1+json', 'Content-Type: application/json' ]; $response = httpRequest('POST', "$host/api/refresh-tokens", $headers, $tokenBody); $jsonResponse = json_decode($response, true); if (isset($jsonResponse["_embedded"]["accessToken"]["securityToken"])) { return $jsonResponse["_embedded"]["accessToken"]["securityToken"]; } else { throw new Exception("Token not retrieved successfully"); } } function findDataSourceForSourceNameAtClient($host, $token, $sourceName) { $headers = [ 'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . mt_rand() . ', token=' . $token, 'Accept: application/vnd.yellowfin.api-v1+json', 'Content-Type: application/json' ]; $response = httpRequest('GET', "$host/api/data-sources", $headers); $jsonObject = json_decode($response); if (isset($jsonObject->items)) { foreach ($jsonObject->items as $source) { if ($source->sourceName === $sourceName) { return $source->sourceId; } } } echo "Data Source could not be found for name: $sourceName\n"; exit(-1); } function httpRequest($method, $url, $headers, $data = null) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); if ($data !== null) { curl_setopt($ch, CURLOPT_POSTFIELDS, $data); } $response = curl_exec($ch); if (curl_errno($ch)) { throw new Exception('Error: ' . curl_error($ch)); } curl_close($ch); return $response; } main(); ?>
import random import time import requests def main(): print("Attach a Tenant Source to Primary Org Source for Source Substitution") host = "http://localhost:8080/Yellowfin" rest_username = "admin@yellowfin.com.au" rest_password = "test" primary_source_name = "PostgreSQL Connection at Primary Org" client_source_name = "PostgreSQL Connection for NEWCLIENT" client_org_reference = "NEWCLIENT" try: client_token = generate_token(host, rest_username, rest_password, client_org_reference) client_org_source_id = find_data_source_for_source_name_at_client(host, client_token, client_source_name) print("Client Org Source Id:", client_org_source_id) primary_token = generate_token(host, rest_username, rest_password, None) primary_org_source_id = find_data_source_for_source_name_at_client(host, primary_token, primary_source_name) print("Primary Org Source Id:", primary_org_source_id) headers = { 'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={random.randint(0, 2**63 - 1)}, token={primary_token}', 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' } url = f'{host}/api/data-sources/{primary_org_source_id}/client-data-sources/?clientSourceId={client_org_source_id}' response = requests.get(url, headers=headers) response.raise_for_status() print(response.text) except Exception as e: print(f"Error: {e}") def find_data_source_for_source_name_at_client(host, token, source_name): headers = { 'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={random.randint(0, 2**63 - 1)}, token={token}', 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' } url = f'{host}/api/data-sources' response = requests.get(url, headers=headers) response.raise_for_status() json_data = response.json() items = json_data.get('items', []) for source in items: if source['sourceName'] == source_name: return source['sourceId'] raise Exception(f"Data Source could not be found for name: {source_name}") def generate_token(host, username, password, tenant_client_org_ref_id): body = { "userName": username, "password": password } if tenant_client_org_ref_id: body['clientOrgRef'] = tenant_client_org_ref_id headers = { 'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={random.randint(0, 2**63 - 1)}', 'Accept': 'application/vnd.yellowfin.api-v1+json', 'Content-Type': 'application/json' } response = requests.post(f'{host}/api/refresh-tokens', headers=headers, json=body) response.raise_for_status() json_response = response.json() access_token = json_response["_embedded"]["accessToken"]["securityToken"] print("Access Token:", access_token) return access_token if __name__ == "__main__": main()
- No labels