In the scenario where ISV clients are installing on-premise, it is sometimes necessary to bundle pre-built content with the installation itself. Pre-built content would generally exist in the form of YFX files that were exported from another instance of Yellowfin where the master-copy of the content was authored.
There are several ways to import content into Yellowfin. It could be imported manually through the UI itself, or automatically installed as part of Yellowfin’s installation. There are two ways automated importing can be achieved, via the REST API or via the Standalone Importer
Importing via the Standalone Command Line Importer
The Standalone Importer can work without Yellowfin actually running. It can connect to the repository database directly and import content contained in a YFX file.
The command line importer can be run from the command line with following command:
java -cp "appserver/webapps/ROOT/WEB-INF/lib/*:appserver/lib/*" com.hof.standalone.ImportData <properties file> <import file>
The classpath (-cp) parameter may require different quoting on different operating systems. The above command has the correct classpath for executing the command in the Yellowfin directory.
The <properties> file defines the connection details for the Yellowfin repository database. An example import.properties is located in Yellowfin/development/examples/standalone/import.properties on a standard install.
The <import file> is a YFX or XML that has been exported from Yellowfin.
Importing via the REST API
Content can be imported into Yellowfin via the POST /api/rpc/import-export/import-content end-point, Import Content. When performing an import of initial content the Yellowfin service will need to be started, which could happen directly after installing Yellowfin itself.
The following code examples illustrate how to import a specified YFX file via the REST API. These consist of two requests to the /api/rpc/import-export end-point. The initial request enumerates the content contained in the export file. The second request imports the export file with importOptions created from the initial request, to add all the content, and skip none.
package rest.code.examples; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; 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 YFX file via the Yellowfin REST API */ public class ImportYFXFile { public static void main(String[] args) throws Exception { System.out.println("Import YFX File"); String host = "http://localhost:8080/Yellowfin"; String restUsername = "admin@yellowfin.com.au"; String restPassword = "test"; String fileToImport = "/Downloads/Test.yfx"; Path importFile = Paths.get(fileToImport); byte[] fileContents = Files.readAllBytes(importFile); String token = generateToken(host, restUsername, restPassword); // Upload File for initial analysis, and to fetch the number of import items. HttpEntity getImportFileContentMulitpartEntity = MultipartEntityBuilder .create() .setMode(HttpMultipartMode.LEGACY) .setCharset(Charset.forName("UTF-8")) .addBinaryBody("contentToProcess", fileContents , ContentType.DEFAULT_BINARY, importFile.getFileName().toString()) .build(); System.out.println("Getting Import File Contents"); Content getImportContentContent = Request.post(host + "/api/rpc/import-export/get-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", getImportFileContentMulitpartEntity.getContentType()) .addHeader("cache-control", "no-cache") .body(getImportFileContentMulitpartEntity) .execute() .returnContent(); JsonObject jsonObject = new JsonParser().parse(getImportContentContent.asString()).getAsJsonObject(); JsonElement itemList = jsonObject.get("items"); JsonArray items = itemList.getAsJsonArray(); // List content, and generate importOptions for each item, setting it to SKIP=false and OPTION=ADD. String importOptions = "; for (int i=0; i < items.size(); i++ ) { JsonObject item = items.getAsJsonArray().get(i).getAsJsonObject(); System.out.println("Item " + i + " " + item.get("resourceType").getAsString() + " " + item.get("resourceName").getAsString() + " found"); if (i>0) { importOptions = importOptions + ","; } importOptions = importOptions + "{ \"itemIndex\": " + i + ", \"optionKey\": \"SKIP\", \"optionValue\": false }, { \"itemIndex\": " + i + ", \"optionKey\": \"OPTION\", \"optionValue\": \"ADD\" }"; } // Upload File for for import, with import options populated HttpEntity importContentMultipartEntity = MultipartEntityBuilder .create() .setMode(HttpMultipartMode.LEGACY) .setCharset(Charset.forName("UTF-8")) .addBinaryBody("contentToProcess", fileContents , ContentType.DEFAULT_BINARY, importFile.getFileName().toString()) .addTextBody("importOptions", "[" + importOptions + "]", ContentType.APPLICATION_JSON) .build(); System.out.println("Importing Content"); Content importContentContent = 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", importContentMultipartEntity.getContentType()) .addHeader("cache-control", "no-cache") .body(importContentMultipartEntity) .execute() .returnContent(); System.out.println("Content Import Complete"); System.out.println(importContentContent.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 System.Text; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace YellowfinAPIExamples { public class ImportYFXFile { static async Task Main(string[] args) { Console.WriteLine("Import YFX File"); string host = "http://localhost:8080/Yellowfin"; string restUsername = "admin@yellowfin.com.au"; string restPassword = "test"; string fileToImport = "/Downloads/Test.yfx"; byte[] fileContents = await File.ReadAllBytesAsync(fileToImport); string token = await GenerateToken(host, restUsername, restPassword); // Upload File for initial analysis, and to fetch the number of import items. var getImportFileContentMultipartContent = new MultipartFormDataContent { { new ByteArrayContent(fileContents), "contentToProcess", Path.GetFileName(fileToImport) } }; Console.WriteLine("Getting Import File Contents"); 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 getImportContentResponse = await httpClient.PostAsync($"{host}/api/rpc/import-export/get-import-content", getImportFileContentMultipartContent); string getImportContentResponseBody = await getImportContentResponse.Content.ReadAsStringAsync(); JObject jsonObject = JObject.Parse(getImportContentResponseBody); JArray items = (JArray)jsonObject["items"]; // List content, and generate importOptions for each item, setting it to SKIP=false and OPTION=ADD. StringBuilder importOptionsBuilder = new StringBuilder(); for (int i = 0; i < items.Count; i++) { JObject item = (JObject)items[i]; Console.WriteLine($"Item {i} {item["resourceType"]} {item["resourceName"]} found"); if (i > 0) { importOptionsBuilder.Append(","); } importOptionsBuilder.Append($"{{ \"itemIndex\": {i}, \"optionKey\": \"SKIP\", \"optionValue\": false }}, {{ \"itemIndex\": {i}, \"optionKey\": \"OPTION\", \"optionValue\": \"ADD\" }}"); } string importOptions = importOptionsBuilder.ToString(); // Upload File for import, with import options populated var importContentMultipartContent = new MultipartFormDataContent { { new ByteArrayContent(fileContents), "contentToProcess", Path.GetFileName(fileToImport) }, { new StringContent($"[{importOptions}]", Encoding.UTF8, "application/json"), "importOptions" } }; Console.WriteLine("Importing Content"); var importContentResponse = await httpClient.PostAsync($"{host}/api/rpc/import-export/import-content", importContentMultipartContent); string importContentResponseBody = await importContentResponse.Content.ReadAsStringAsync(); Console.WriteLine("Content Import Complete"); Console.WriteLine(importContentResponseBody); } } /* * This function generates an access token for a user that will grant them access to * call REST API endpoints. */ static async Task<string> GenerateToken(string host, string username, string password) { using (var client = new HttpClient()) { long nonce = new Random().NextInt64(); 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 }), Encoding.UTF8, "application/json"); HttpResponseMessage response = await client.SendAsync(request); string responseContent = await response.Content.ReadAsStringAsync(); JObject jsonObject = JObject.Parse(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" "mime/multipart" "net/http" "path/filepath" "strings" "time" ) func main() { fmt.Println("Import YFX File") host := "http://localhost:8080/Yellowfin" restUsername := "admin@yellowfin.com.au" restPassword := "test" fileToImport := "/Downloads/Test.yfx" fileContents, err := ioutil.ReadFile(fileToImport) if err != nil { fmt.Println("Error reading file:", err) return } token, err := generateToken(host, restUsername, restPassword) if err != nil { fmt.Println("Error generating token:", err) return } // Upload File for initial analysis, and to fetch the number of import items. var buf bytes.Buffer writer := multipart.NewWriter(&buf) part, err := writer.CreateFormFile("contentToProcess", filepath.Base(fileToImport)) if err != nil { fmt.Println("Error creating form file:", err) return } part.Write(fileContents) writer.Close() req, err := http.NewRequest("POST", fmt.Sprintf("%s/api/rpc/import-export/get-import-content", host), &buf) 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") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return } defer resp.Body.Close() getImportContentContent, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response body:", err) return } var jsonObject map[string]interface{} if err := json.Unmarshal(getImportContentContent, &jsonObject); err != nil { fmt.Println("Error parsing JSON response:", err) return } items := jsonObject["items"].([]interface{}) var importOptions strings.Builder for i, item := range items { itemMap := item.(map[string]interface{}) fmt.Printf("Item %d %s %s found\n", i, itemMap["resourceType"].(string), itemMap["resourceName"].(string)) if i > 0 { importOptions.WriteString(",") } importOptions.WriteString(fmt.Sprintf(`{ "itemIndex": %d, "optionKey": "SKIP", "optionValue": false }, { "itemIndex": %d, "optionKey": "OPTION", "optionValue": "ADD" }`, i, i)) } // Upload File for import, with import options populated buf.Reset() writer = multipart.NewWriter(&buf) part, err = writer.CreateFormFile("contentToProcess", filepath.Base(fileToImport)) if err != nil { fmt.Println("Error creating form file:", err) return } part.Write(fileContents) writer.WriteField("importOptions", fmt.Sprintf("[%s]", importOptions.String())) writer.Close() req, err = http.NewRequest("POST", fmt.Sprintf("%s/api/rpc/import-export/import-content", host), &buf) 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, 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() importContentContent, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response body:", err) return } fmt.Println("Content Import Complete") fmt.Println(string(importContentContent)) } /* * This function generates an access token for a user that will grant them access to * call REST API endpoints. */ func generateToken(host, username, password string) (string, error) { nonce := rand.Int63() requestBody, err := json.Marshal(map[string]string{ "userName": username, "password": password, }) if err != nil { fmt.Println("Error marshaling request body:", err) return ", err } client := &http.Client{} request, err := http.NewRequest("POST", fmt.Sprintf("%s/api/refresh-tokens", host), 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{} if err := json.Unmarshal(responseBody, &jsonResponse); 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") } fmt.Println("Access Token:", accessToken) return accessToken, nil }
const fetch = require("node-fetch"); const fs = require("fs"); const path = require("path"); const FormData = require("form-data"); async function main() { console.log("Import YFX File"); const host = "http://localhost:8080/Yellowfin"; const restUsername = "admin@yellowfin.com.au"; const restPassword = "test"; const fileToImport = "/Downloads/Test.yfx"; const fileContents = fs.readFileSync(fileToImport); const token = await generateToken(host, restUsername, restPassword); if (token === null) { console.error("Failed to retrieve access token"); return; } // Upload File for initial analysis, and to fetch the number of import items const form1 = new FormData(); form1.append("contentToProcess", fileContents, path.basename(fileToImport)); const nonce1 = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); const headers1 = { 'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce1}, token=${token}`, 'Accept': 'application/vnd.yellowfin.api-v1+json', 'cache-control': 'no-cache', ...form1.getHeaders() }; try { console.log("Getting Import File Contents"); const response1 = await fetch(`${host}/api/rpc/import-export/get-import-content`, { method: 'POST', headers: headers1, body: form1 }); if (!response1.ok) { throw new Error(`HTTP error! Status: ${response1.status}`); } const getImportContentContent = await response1.json(); const items = getImportContentContent.items; // List content, and generate importOptions for each item, setting it to SKIP=false and OPTION=ADD let importOptions = items.map((item, i) => { console.log(`Item ${i} ${item.resourceType} ${item.resourceName} found`); return [ `{ "itemIndex": ${i}, "optionKey": "SKIP", "optionValue": false }`, `{ "itemIndex": ${i}, "optionKey": "OPTION", "optionValue": "ADD" }` ]; }).flat().join(", "); // Upload File for import, with import options populated const form2 = new FormData(); form2.append("contentToProcess", fileContents, path.basename(fileToImport)); form2.append("importOptions", `[${importOptions}]`); const nonce2 = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); const headers2 = { 'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce2}, token=${token}`, 'Accept': 'application/vnd.yellowfin.api-v1+json', 'cache-control': 'no-cache', ...form2.getHeaders() }; console.log("Importing Content"); const response2 = await fetch(`${host}/api/rpc/import-export/import-content`, { method: 'POST', headers: headers2, body: form2 }); if (!response2.ok) { throw new Error(`HTTP error! Status: ${response2.status}`); } const importContentContent = await response2.text(); console.log("Content Import Complete"); console.log(importContentContent); } catch (error) { console.error("Error:", error.message); } } /* * This function generates an access token for a user that will grant them access to * call REST API endpoints. */ async function generateToken(host, username, password) { // 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: username, password: password }); 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() { echo "Import YFX File\n"; $host = "http://localhost:8080/Yellowfin"; $restUsername = "admin@yellowfin.com.au"; $restPassword = "test"; $fileToImport = "/Downloads/Test.yfx"; $fileContents = file_get_contents($fileToImport); try { $token = generateToken($host, $restUsername, $restPassword); } catch (Exception $e) { echo "Error generating token: " . $e->getMessage(); return; } // Upload File for initial analysis, and to fetch the number of import items. $getImportFileContentMultipartEntity = buildMultipartEntityForAnalysis($fileContents, basename($fileToImport)); echo "Getting Import File Contents\n"; try { $getImportContentContent = sendMultipartRequest($host, $token, $getImportFileContentMultipartEntity, "/api/rpc/import-export/get-import-content"); } catch (Exception $e) { echo "Error sending request: " . $e->getMessage(); return; } $jsonObject = json_decode($getImportContentContent, true); $items = $jsonObject['items']; // List content, and generate importOptions for each item, setting it to SKIP=false and OPTION=ADD. $importOptions = []; foreach ($items as $i => $item) { echo "Item $i " . $item['resourceType'] . " " . $item['resourceName'] . " found\n"; $importOptions[] = [ "itemIndex" => $i, "optionKey" => "SKIP", "optionValue" => false ]; $importOptions[] = [ "itemIndex" => $i, "optionKey" => "OPTION", "optionValue" => "ADD" ]; } // Upload File for import, with import options populated $importContentMultipartEntity = buildMultipartEntity($fileContents, basename($fileToImport), json_encode($importOptions)); echo "Importing Content\n"; try { $importContentContent = sendMultipartRequest($host, $token, $importContentMultipartEntity, "/api/rpc/import-export/import-content"); echo "Content Import Complete\n"; echo $importContentContent; } catch (Exception $e) { echo "Error sending request: " . $e->getMessage(); } } /* * This function generates an access token for a user that will grant them access to * call REST API endpoints. */ function generateToken($host, $username, $password) { // Generate nonce $nonce = mt_rand(); // Create request headers $headers = [ 'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . $nonce, 'Accept: application/vnd.yellowfin.api-v1+json', 'Content-Type: application/json' ]; // Create request body $body = json_encode([ "userName" => $username, "password" => $password ]); // Make POST request $response = httpRequest('POST', "$host/api/refresh-tokens", $headers, $body); // Parse JSON response $jsonResponse = json_decode($response, true); if (isset($jsonResponse["_embedded"]["accessToken"]["securityToken"])) { $accessToken = $jsonResponse["_embedded"]["accessToken"]["securityToken"]; echo "Access Token: $accessToken\n"; return $accessToken; } else { throw new Exception("Token not retrieved successfully"); } } function buildMultipartEntityForAnalysis($fileContents, $fileName) { $boundary = uniqid(); $multipartBody = "--$boundary\r\n"; $multipartBody .= 'Content-Disposition: form-data; name="contentToProcess"; filename="' . $fileName . "\"\r\n"; $multipartBody .= "Content-Type: application/octet-stream\r\n\r\n"; $multipartBody .= $fileContents . "\r\n"; $multipartBody .= "--$boundary--"; return $multipartBody; } function buildMultipartEntity($fileContents, $fileName, $importOptions) { $boundary = uniqid(); $multipartBody = "--$boundary\r\n"; $multipartBody .= 'Content-Disposition: form-data; name="contentToProcess"; filename="' . $fileName . "\"\r\n"; $multipartBody .= "Content-Type: application/octet-stream\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 .= $importOptions . "\r\n"; $multipartBody .= "--$boundary--"; return $multipartBody; } function sendMultipartRequest($host, $token, $multipartBody, $endpoint) { $boundary = substr($multipartBody, 2, strpos($multipartBody, "\r\n") - 2); $headers = [ '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=' . $boundary, 'cache-control: no-cache' ]; $response = httpRequest('POST', "$host$endpoint", $headers, $multipartBody); return $response; } 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" file_to_import = "/Downloads/Test.yfx" try: with open(file_to_import, 'rb') as f: file_contents = f.read() except IOError as e: print(f"Error reading file: {e}") return try: token = generate_token(host, rest_username, rest_password) except Exception as e: print(f"Error generating token: {e}") return # Upload File for initial analysis, and to fetch the number of import items files = { 'contentToProcess': ('Test.yfx', file_contents, 'application/octet-stream') } 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', 'cache-control': 'no-cache' } print("Getting Import File Contents") try: response = requests.post(f"{host}/api/rpc/import-export/get-import-content", headers=headers, files=files) response.raise_for_status() import_content = response.json() except requests.RequestException as e: print(f"Error getting import file contents: {e}") return items = import_content.get("items", []) import_options = [] for i, item in enumerate(items): print(f"Item {i} {item['resourceType']} {item['resourceName']} found") import_options.append({ "itemIndex": i, "optionKey": "SKIP", "optionValue": False }) import_options.append({ "itemIndex": i, "optionKey": "OPTION", "optionValue": "ADD" }) import_options_json = json.dumps(import_options) # Upload File for import, with import options populated files = { 'contentToProcess': ('Test.yfx', file_contents, 'application/octet-stream'), 'importOptions': (None, import_options_json, 'application/json') } print("Importing Content") try: response = requests.post(f"{host}/api/rpc/import-export/import-content", headers=headers, files=files) response.raise_for_status() print("Content Import Complete") print(response.text) except requests.RequestException as e: print(f"Error importing content: {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' } 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") if __name__ == "__main__": main()