Tutorial Part 1: Laying the Foundation

Ingest raw asset data and discover the first automatic relationships.


Part 1: Laying the Foundation - From Raw Data to a Connected Graph

Goal: In this part, we will ingest raw asset data for a hybrid cloud environment. This data describes what our applications are and what they need, but not where they are hosted. We’ll see how rescile discovers initial relationships and vendor dependencies from this simple data.

Step 1: Ingesting the Core Application Assets

Let’s start by defining our core assets: the applications themselves. We’ll create a single CSV file in the data/assets directory. The filename becomes the resource type (application), and the column headers become the properties of each resource.

Notice the domain column. This property describes the logical environment where the application is intended to run, such as a core banking system domain versus an operational monitoring domain. This property will be the source for our first modeling rule.

data/assets/application.csv

name,function,domain,datastore
dataguard,replication,core,OracleDB
zabbix,monitoring,operation,PostgreSQL
asseteditor,management,access,
openbao,encryption,operation,

Now, let’s build and serve the graph. Restart the server from the previous step.

rescile-ce serve

Result: The graph now contains a set of disconnected (application) nodes. You can verify this in the GraphiQL UI at http://localhost:7600 by running a query:

query GetApplications {
  application {
    name
    function
    domain
  }
}

This demonstrates how rescile ingests assets from simple flat files. The graph currently looks like this:

graph TD subgraph "Applications" A1["application
dataguard
{domain: core}"] A2["application
zabbix
{domain: operation}"] A3["application
asseteditor
{domain: access}"] A4["application
openbao
{domain: operation}"] end

Step 2: Creating Resources from Properties

Now, let’s connect our assets by creating new resources based on their properties. We will create our first model file. This model will read the domain property from each (application) and create a distinct (domain) resource for each unique value it finds (core, operation, access).

Create the following model file:

data/models/domain.toml

# This model finds the 'domain' property on an application
# and creates a distinct (domain) resource for it.
origin_resource = "application"

[[create_resource]]
# Read the 'domain' property from the application.
create_from_property = "domain"
# Create a relationship of this type from the application to the new domain.
relation_type = "USE_SERVICE"
[create_resource.properties]
# We can add new properties to the domain resource we are creating.
# This templated description uses properties from the source application.
function = "hosting"
description = "The {{origin_resource.domain}} domain creates secure boundaries for management, maintenance, and operation of {{origin_resource.function}} resources."
subscription = "finnova"
created = "{{now(utc=true) | date(format='%Y-%m-%dT%H:%M:%SZ')}}"

Save the file and run rescile-ce serve again.

Result: The graph is now connected! The domain.toml model has created three new (domain) nodes and linked the (application) nodes to them with a USE_SERVICE relationship.

Verify the new connections with this GraphQL query, which traces from the domain down to the applications it contains:

query GetDomainsAndApps {
  domain {
    name
    application {
      node {
        name
      }
    }
  }
}

The resulting graph now shows the dependencies:

graph TD A1["application
dataguard"] -- USE_SERVICE --> D1["domain
core"] A2["application
zabbix"] -- USE_SERVICE --> D2["domain
operation"] A4["application
openbao"] -- USE_SERVICE --> D2 A3["application
asseteditor"] -- USE_SERVICE --> D3["domain
access"]

We’ve successfully ingested our raw assets and used our first declarative model to create a new layer of resources, forming a connected blueprint.