Skip to content
/ clay Public

An abstract system model store to automate various kind of operations

License

Notifications You must be signed in to change notification settings

qb0C80aE/clay

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Clay

Build Status License: MIT

Clay is an abstract system model store to automate various kind of operations.
It provides some APIs to access the system model store.



Logo
License: CC BY-SA 4.0
logo: By Derzsi Elekes Andor (Own work)
via Wikimedia Commons

Concept ans usecases

Clay is a simple client tool that enables you to define various kind of models what you need, to register and pull those model data, and to generate data what you want like program code, text data using those models through REST API. It concentrates on those tasks in order to help you to try such as Infrastructure as Code, DevOps.

Clay itself does not manage any data, and leaves the management of data to versioning systems like Git, which are good at managing versions of human-readable text data. On Clay, you can build models, retrieve them as JSON or something human-readable, and then, manage them in Git. If you want to edit them again, all you have to do is just registering them to Clay again through API.

Concept

Suppose that there are developers, and non-programmer system administrators. Admins can offer their meaningful operation sequences as commands, and using them, developers can create code templates for orchestrators, testers, automation tools, or small shell scripts in order to make machines process those things.

By working together, they might be able to get sophisticated techniques of each other. After getting used to the situation, might become to start to code their infrastructure together.

Clay is designed not to disturb their original work as possible. This is also the reason why Clay is provided as a single binary that does not cause dependency/install problems at use time, in order to get them to focus on their main work. If they have become to code their works together by learning how to code their infrastructure and operations through Clay, then they can throw away Clay and manage their systems with their code only.

Usecase

Generally, design information like network diagram drawn with illustration tools are not reusable for machines to process, furthermore, this kind of information is tend to get different from its actual implementation. As a result, people have to sync them manually. If you can design and view your system on GUI, and can apply that? Clay might allow you to be able to sync those two in some better ways.

Download binaries

Demo

Live (GUI)

You can experience a live demo here.

Screenshots

There are two examples. The first one is api only example, the second one is api and GUI example.
Clay expresses this GUI by considering its templates or scripts, objects in its model store as html, js, css, or raw image objects.

If you don't need, you don't have to implement GUI like this, it's just an example. You can use Clay in various ways you want, such as infrastructure design, graph output for nwdiag using templates, etc. Of course, you can implement external GUI tool using Clay as a backend, but keep it in your mind that Clay is just a client tool.

Sample UI - network design (L1)

Sample UI - network design (L1)

Sample UI - network design (VLAN)

Sample UI - network design (VLAN)

Sample UI - network design (L3)

Sample UI - network design (L3)

This sample GUI is using inet-henge to draw diagrams.

Example: Using template to generate nwdiag json

nwdiag template nwdiag output

Example: Using template to convert models to Neo4j cypher

neo4j conversion_1 neo4j conversion_2

Example: Using template to convert models to RFC 8345/8346

rfc8345 conversion

How to use

Just download Clay binary and run.

$ ./clay

The server runs at http://localhost:8080 by default.

If you give -h to Clay, you can see the help. The default running mode is server, and Clay has also client functions to store or retrieve data.

If it's the first time to use Clay, run examples are recommended to know what you can on Clay. This operation boots Clay with an example.

$ CLAY_CONFIG_FILE_PATH=examples/api_only/clay_config.json ./clay

If you want to try sample GUI, do like below.

$ CLAY_CONFIG_FILE_PATH=examples/api_and_gui/clay_config.json ./clay

Then access http://localhost:8080/ui in your browser.

Environmental variables

You can give some environmental variables to Clay in order to control its behavior.

Key Description Options Default
CLAY_CONFIG_FILE_PATH The config file path. - ./clay_config.json
CLAY_HOST The host to listen. - localhost
CLAY_PORT The port to listen. - 8080
CLAY_DB_MODE The indentifier how its db is managed. memory/file file
CLAY_DB_FILE_PATH The path where its db file is located. This value is used if DB_MODE=file is set. - clay.db
CLAY_ASSET_MODE The indentifier how its assets is managed. external/internal external

Basic REST API access

After booting Clay, you can know what endpoints exist by accessing root path.

$ curl http://localhost:8080/
[
    "designs_url [DELETE] http://localhost:8080/designs/present",
    "designs_url [GET] http://localhost:8080/designs/present",
    "designs_url [PUT] http://localhost:8080/designs/present",
    "ephemeral_binary_object_raws_url [GET] http://localhost:8080/ephemeral_binary_objects/:name/raw",
    "ephemeral_binary_objects_url [DELETE] http://localhost:8080/ephemeral_binary_objects/:name",
    "ephemeral_binary_objects_url [GET] http://localhost:8080/ephemeral_binary_objects",
    "ephemeral_binary_objects_url [GET] http://localhost:8080/ephemeral_binary_objects/:name",
    "ephemeral_binary_objects_url [POST] http://localhost:8080/ephemeral_binary_objects",
    "ephemeral_binary_objects_url [PUT] http://localhost:8080/ephemeral_binary_objects/:name",
    "ephemeral_script_executions_url [DELETE] http://localhost:8080/ephemeral_scripts/:name/execution",
    "ephemeral_script_executions_url [POST] http://localhost:8080/ephemeral_scripts/:name/execution",
    "ephemeral_script_raws_url [GET] http://localhost:8080/ephemeral_scripts/:name/raw",
    "ephemeral_scripts_url [DELETE] http://localhost:8080/ephemeral_scripts/:name",
    "ephemeral_scripts_url [GET] http://localhost:8080/ephemeral_scripts",
    "ephemeral_scripts_url [GET] http://localhost:8080/ephemeral_scripts/:name",
    "ephemeral_scripts_url [POST] http://localhost:8080/ephemeral_scripts",
    "ephemeral_scripts_url [PUT] http://localhost:8080/ephemeral_scripts/:name",
    "ephemeral_template_generations_url [GET] http://localhost:8080/ephemeral_templates/:name/generation",
    "ephemeral_template_raws_url [GET] http://localhost:8080/ephemeral_templates/:name/raw",
    "ephemeral_templates_url [DELETE] http://localhost:8080/ephemeral_templates/:name",
    "ephemeral_templates_url [GET] http://localhost:8080/ephemeral_templates",
    "ephemeral_templates_url [GET] http://localhost:8080/ephemeral_templates/:name",
    "ephemeral_templates_url [POST] http://localhost:8080/ephemeral_templates",
    "ephemeral_templates_url [PUT] http://localhost:8080/ephemeral_templates/:name",
    "template_arguments_url [DELETE] http://localhost:8080/template_arguments/:key_parameter(default=id)",
    "template_arguments_url [GET] http://localhost:8080/template_arguments",
    "template_arguments_url [GET] http://localhost:8080/template_arguments/:key_parameter(default=id)",
    "template_arguments_url [POST] http://localhost:8080/template_arguments",
    "template_arguments_url [PUT] http://localhost:8080/template_arguments/:key_parameter(default=id)",
    "template_generations_url [GET] http://localhost:8080/templates/:key_parameter(default=id)/generation",
    "template_raws_url [GET] http://localhost:8080/templates/:key_parameter(default=id)/raw",
    "templates_url [DELETE] http://localhost:8080/templates/:key_parameter(default=id)",
    "templates_url [GET] http://localhost:8080/templates",
    "templates_url [GET] http://localhost:8080/templates/:key_parameter(default=id)",
    "templates_url [POST] http://localhost:8080/templates",
    "templates_url [PUT] http://localhost:8080/templates/:key_parameter(default=id)",
    "url_alias_definitions_url [GET] http://localhost:8080/url_alias_definitions",
    "url_alias_definitions_url [GET] http://localhost:8080/url_alias_definitions/:name",
    "url_alias_definitions_url [POST] http://localhost:8080/url_alias_definitions",
    "user_defined_model_definitions_url [GET] http://localhost:8080/user_defined_model_definitions",
    "user_defined_model_definitions_url [GET] http://localhost:8080/user_defined_model_definitions/:type_name",
    "user_defined_model_definitions_url [POST] http://localhost:8080/user_defined_model_definitions"
]

You can access Clay with GET, POST, PUT, and DELETE methods.

Here are examples with curl.

$ curl -X POST -H "Content-Type: application/json" "localhost:8080/nodes" -d '{"name": "Node1", "node_type_id": 1}'
$ curl -X POST -H "Content-Type: application/json" "localhost:8080/nodes" -d '{"name": "Node2", "node_type_id": 1, "ports": [{"name": "port1", "number": 1}]}'
$ curl -X POST -H "Content-Type: application/json" "localhost:8080/nodes" -d '{"id": 100, "name": "Node100", "node_type_id": 2}'
$ curl -X POST -H "Content-Type: application/x-yaml" "localhost:8080/nodes" --data-binary @- <<EOF
id: 102
name: Node102
description: ""
node_type_id: 3
EOF
$ curl -X POST -H "Content-Type: multipart/form-data" "localhost:8080/templates" -F name="template1" -F template_content=@examples/api_only/sample.template
$ curl -X PUT -H "Content-Type: application/json" "localhost:8080/nodes/1" -d '{"name": "NodeX", "node_type_id": 2}'
$ curl -X GET "localhost:8080/nodes"
$ curl -X GET "localhost:8080/nodes/1"
$ curl -X DELETE "localhost:8080/nodes/1"

When you POST or PUT data, you have to specify Content-Type header to application/json, application/x-yaml, or multipart/form-data. If you want GET data from Clay in YAML, specify Accept header to applicaton/x-yaml.

$ curl -H "Accept: application/x-yaml" "localhost:8080/nodes"

Queries for single (like /templates/1) and multiple (like /templates) resource urls

  • fields
  • preloads
  • pretty

Here are examples with curl.

$ curl "localhost:8080/nodes?preloads=ports.link.destination_port.node,routes.output_port" # Select nodes and their ports with their link.destination_port.node, and routes with their output_port.
$ curl "localhost:8080/nodes?preloads=ports&fields=id,ports.id,ports.name" # Select nodes and their ports, and extract id of nodes, and id, names of ports.
$ curl "localhost:8080/nodes?pretty" # Select nodes and format results.

Queries for single resource url

  • key_parameter

Here are examples with curl.

$ curl "localhost:8080/nodes/1" # Select a node which has the id 1. It's the default behavior.
$ curl "localhost:8080/nodes/Node1?key_parameter=name" # Select a node which has the name Node1. It identifies a single resource by using name instead of id.

Note that if you give Clay a non-unique field name as key_parameter, Clay will return the first record in specified order, which means, the parameter does not mean the identifier any longer, in that case.

You can know resources which can be identified by key_parameter, by accessing root path.

curl "localhost:8080"
...
nodes_url [GET] http://localhost:8080/nodes/:key_parameter(default=id)
...

Queries for multiple resource url

  • q[field_name]
  • sort
  • first
  • page
  • limit

Here are examples with curl.

$ curl "localhost:8080/templates?q\[name\]=Template1,Template2&q\[description\]=" # Select templates which has the name Template1 or Template2, and description is empty, as multiple results
$ curl "localhost:8080/templates?q\[name\]=%25Template%25" # Select templates which has the name like ...Template... as multiple results
$ curl "localhost:8080/templates?q\[name\]=%21Template1&sort=+id&first" # Select templates which name is not Template1, and sort by id ascend, then pick up the first one as a single result
$ curl "localhost:8080/templates?q\[name\]=null" # Select templates which name is null as multiple results
$ curl "localhost:8080/nodes?limit=2&page=2" # Select nodes limiting the count of result records up to 2 and specifying the result set page. This operation retrieves the record 3-4.

User defined models

The one of main features of Clay is defining models through REST API at runtime or boot time without recompiling Clay binary. The model definition is described in JSON or YAML format, and it's handled as Golang struct in Clay. This model definition is bound with tables or view in the database, so you can define data models in various ways as you want using well known language, SQL.

The models may be the ones what you need and consider based on your business, or the standard models like RFC 8345 - A YANG Data Model for Network Topologies and RFC 8346 - A YANG Data Model for Layer 3 Topologies. Clay can handle any models if you describe and register those.

Clay's Rest API is using Gin(framework) & GORM(orm). Which means, by defining Golang struct field tags, various features like json/yaml marshal, GORM instruction, or field validation, will be available.

{
  "type_name": <string>,                   # Type Name. You can refer this name in field definitions to use user defined types.
  "resource_name": <string>,               # Resouce Name. It's used as REST resource name, and DB table name.
  "to_be_migrated": <bool>,                # If it's true, a table it's name is resource_name will be created in DB, and it will be appear in design.
  "is_controller_enabled": <bool>,         # If it's true, a controller will be enabled, and REST endpoint will appear.
  "is_design_access_disabled": <bool>,     # If it's true, this resource will be ignored at design import/export.
  "is_many_to_many_association": <bool>,   # It it's true, this resouce will be handled as many-to-many relationship object like
  "fields": [                              # Struct fields.
    {
      "name": <string>,                    # Field Name.
      "tag": <string>,                     # Golang struct tag like json, yaml, sql, gorm.
      "type_name": <string>,               # Type Name. You can use int, uint, float, string, bool, and also refer a type_name of model definitionto use user defined types.
      "is_slice": <bool>                   # If it's true, this field will be handled as an slice.
    },
    ...
  ],
  "sql_before_migration": [                # A list of string which will be executed as SQL before model migration.
    <string>, ...                          # You can use ';' in order to execute multiple SQL at once.
  ],
  "sql_after_migration": [                 # A list of string which will be executed as SQL after model migration.
    <string>, ...
  ],
  "sql_where_for_design_extraction": [     # A list of string which will be executed as SQL where sentence at design extraction.
    <string>, ...
  ],
  "sql_where_for_design_deletion": [       # A list of string which will be executed as SQL where sentence at design deletion.
    <string>, ...
  ]
}

Here is an example.

{
  "type_name": "Node",                   # Type Name. You can refer this name in field definitions to use user defined types.
  "resource_name": "nodes",              # Resouce Name. It's used as REST resource name, and DB table name.
  "to_be_migrated": true,                # If it's true, a table it's name is resource_name will be created in DB, and it will be appear in design.
  "is_controller_enabled": true,         # If it's true, a controller will be enabled, and REST endpoint will appear.
  "is_design_access_disabled": false,    # If it's true, this resource will be ignored at design import/export.
  "is_many_to_many_association": false,  # It it's true, this resouce will be handles as many-to-many relationship object like NodeGroupNodeAssociation(see examples).
  "fields": [                            # Field definitions of Node struct.
    {
      "name": "ID",
      "tag": "json:\"id\" yaml:\"id\" gorm:\"primary_key;auto_increment\"",
      "type_name": "int"
    },
    {
      "name": "Name",
      "tag": "json:\"name\" yaml:\"name\" gorm:\"not null;unique\"",
      "type_name": "string"
    },
    {
      "name": "Description",
      "tag": "json:\"description\" yaml:\"description\"",
      "type_name": "string"
    },
    {
      "name": "Ports",
      "tag": "json:\"ports\" yaml:\"ports\" gorm:\"ForeignKey:NodeID\" validate:\"omitempty,dive\"",
      "type_name": "Port",
      "is_slice": true
    },
    {
      "name": "NodeGroupNodeAssociations",
      "tag": "json:\"node_group_node_associations\" yaml:\"node_group_node_associations\" gorm:\"ForeignKey:NodeID\" validate:\"omitempty,dive\"",
      "type_name": "NodeGroupNodeAssociation",
      "is_slice": true
    },
    {
      "name": "Routes",
      "tag": "json:\"routes\" yaml:\"routes\" gorm:\"ForeignKey:NodeID\" validate:\"omitempty,dive\"",
      "type_name": "NodeRoute",
      "is_slice": true
    }
  ]
}

In sql_* fields, You can use any SQL which is allowed in SQLite3, which means, you can define triggers in order to cleanup unnecessary data, or auto generate related data.

If is_controller_enabled is true, those endpoints will appear in the endpoint list after registration.

$ curl -X POST -H "Content-Type: application/json" http://localhost:8080/user_defined_model_definitions -d @examples/api_only/node.json
$ curl http://localhost:8080/
[
    ...
    "nodes_url [DELETE] http://localhost:8080/nodes/:key_parameter(default=id)",
    "nodes_url [GET] http://localhost:8080/nodes",
    "nodes_url [GET] http://localhost:8080/nodes/:key_parameter(default=id)",
    "nodes_url [POST] http://localhost:8080/nodes",
    "nodes_url [PUT] http://localhost:8080/nodes/:key_parameter(default=id)",
    ...
]

As implemented in examples, you can also define views instead of tables in order to pick up data that you need efficiently.

Import and export the design

You can import and export the models you created through designs resource. Clay is designed as a standalone modeling tool, and the created design can be stored as human-readable text files in version management repositories like git to make it easier to realize Infrastructure-as-Code.

Of course, the data related to user defined models will be also available in the design resource, if their is_design_access_disabled field is false.

$ # Import and overwrite the design
$ curl -X PUT 'localhost:8080/designs/present' -H 'Content-Type: application/json' -d @examples/design_example.json
$ # Export the design
$ curl -X GET 'localhost:8080/designs/present?pretty' > design.json

If you have booted Clay with examples, you can see the file below that includes user defined model types after export.

$ cat design.json
{
    "clay_version": "...",
    "content": {
        "links": [...],                             # User-Defined in examples
        "node_group_node_associations": [...],      # User-Defined in examples
        "node_groups": [...],                       # User-Defined in examples
        "node_routes": [...],                       # User-Defined in examples
        "nodes": [...],                             # User-Defined in examples
        "port_group_port_associations": [...],      # User-Defined in examples
        "port_groups": [...],                       # User-Defined in examples
        "port_ipv4_addresses": [...],               # User-Defined in examples
        "ports": [...],                             # User-Defined in examples
        "subnets": [...],                           # User-Defined in examples
        "template_arguments": [...],
        "templates": [...],
        "vlan_port_associations": [...],            # User-Defined in examples
        "vlans": [...]                              # User-Defined in examples
    }
}

Note that SQL triggers will be disabled during design access. One more thing, import and export will be processed following the sequence that models were defined.

Templates

You can register some text templates and generate something using the models in Clay. Templates are written in Golang text/template format. Some functions are provided in template processing, see an example template in Clay like examples/api_only/sample.template.

$ # register template and template arguments
$ curl -X POST -H "Content-Type: multipart/form-data" "localhost:8080/templates" -F id=1 -F name="sample" -F template_content=@examples/api_only/sample.template
$ curl -X POST -H "Content-Type: application/json" "localhost:8080/template_arguments" -d '{"id": 1, "template_id": 1, "name": "testParameter11", "type": "int", "default_value": "1"}'
$ curl -X POST -H "Content-Type: application/json" "localhost:8080/template_arguments" -d '{"id": 2, "template_id": 1, "name": "testParameter12", "type": "int", "default_value": "2"}'
$ # show registered template
$ curl -X GET "localhost:8080/templates/1"
$ # show registered template content
$ curl -X GET "localhost:8080/templates/1/raw"
$ # generate a text from the tempalte
$ curl -X GET "localhost:8080/templates/1/generation"

When you generate a text from template, you can override the default value of template arguments by giving parameter queries.

$ curl -X GET "localhost:8080/templates/1/generation?p\[testParameter12\]=9999"

If you want to get raw data or generated text data in a specific Content-Type, specify Accept and Accept-Charset headers.

$ curl -X GET -H "Accept: application/x-yaml" -H "Accept-Charset: Shift_JIS" "localhost:8080/templates/1/raw"
$ curl -X GET -H "Accept: application/x-yaml" -H "Accept-Charset: Shift_JIS" "localhost:8080/templates/1/generation"

As described earlier, there is a way to design your target, using standard models in the first place. And as another way, you can generate these standard models or other model like Neo4j from your own models using this template function. In detail, see template resources tab in the api_and_gui example.

Ephemeral templates, scripts and objects

Ephemeral something is volatile objects unrelated to designs resource. You can register those items into Clay, but after rebooting, those will disappear. Those are used in various purposes like using as image, css, js or html files, or those templates.

EphemeralScript is using otto which processes JavaScript.

See examples/api_and_gui/ephemeral_* directories to know in detail.

URL aliases

Clay provides url alias feature like request forwarding by registering specific information to Clay through REST API. This feature can be used for various kinds of purpose, such as creating url shortcut, pretending static files.

For example, write alias.json in a specific format like below.

{
  "name": <string>,                 # Name
  "from": <string>,                 # Redirect path from
  "to": <string>,                   # Redirect path to
  "query": <string>,                # Queries added when access is redirected
  "methods": [                      # HTTP methods
    {
      "method": <string>,           # HTTP methods (GET|POST|PUT|DELETE)
      "target_url_type": <string>,  # Target resource url type (multi|single)
      "accept": <string>,           # Accept header value
      "accept_charset": <string>    # Accept-Charset header value
    }
  ]
}

Then, POST it into localhost:8080/url_alias_definitions to register.

$ curl -X POST -H "Accept: application/json" "localhost:8080/url_alias_definitions" -d @alias.json

When you use URL aliases, Content-Type in the response will be determined by accept and accept_charset fields. Note that files will be loaded from the top, which means, you have to regard these loading sequences if used defined models have dependencies like foreign keys, views, or triggers. See clay_config,json in examples to know in detail.

Configuration file

You have seen it so far that you can register various kinds of items into Clay. In addition, by writing the configuration file and specify it at boot time, Clay can register information in that automatically.

{
  "general": {
    "user_defined_models_directory": <string>,
    "ephemeral_templates_directory": <string>,
    "ephemeral_binary_objects_directory": <string>,
    "ephemeral_scripts_directory": <string>
  },
  "user_defined_models": [
    {
      "file_name": <string>
    },
    ...
  ],
  "ephemeral_templates": [
    {
      "name": <string>,
      "file_name": <string>
    },
    ...
  ],
  "ephemeral_binary_objects": [
    {
      "name": <string>,
      "file_name": <string>
    },
    ...
  ],
  "ephemeral_scripts": [
    {
      "name": <string>,
      "file_name": <string>
    },
    ...
  ],
  "url_aliases": [
    <the same format as URL aliases section>,
    ...
  ]
}

If you want to know concrete ways to write, see clay_config.json in examples directory.

How to build

$ # Note: Before you build Clay, you need to install a C compiler lilke gcc in order to build go-sqlite3
$ # Note: Suppose that $HOME is /home/user, and $GOPATH is /home/user/go.
$ # Note: Please install dep, go-assets-builder first.
$ go get -u github.com/golang/dep/cmd/dep
$ go get -u github.com/jessevdk/go-assets-builder
$ dep ensure
$ go generate -tags=prebuild ./...
$ # Note: If you want to build Clay as a statically linked single binary file, add the flag like below.
$ # go build --ldflags '-extldflags "-static"'
$ go build
$ ./clay &

Cross-compile

For example, you can build Clay for Linux 32bit, Windows 32bit and 64bit on Ubuntu.

$ # Suppose that Go is installed, $HOME is /home/user, GOROOT is /usr/local/go, and $GOPATH is /home/user/go.
$ cd $HOME
$ sudo apt-get update
$ # Install required packages.
$ sudo apt-get install -y git wget tar gcc
$ ## For Linux 32bit.
$ sudo apt-get install -y gcc-multilib
$ ## For Windows 64bit and 32bit.
$ sudo apt-get install -y binutils-mingw-w64 mingw-w64
$ # Install go cross-compile environments. It requires go 1.4.
$ wget https://storage.googleapis.com/golang/go1.4.3.linux-amd64.tar.gz
$ mkdir -p $HOME/go1.4
$ tar -C $HOME/go1.4 --strip-components 1 -xzf go1.4.3.linux-amd64.tar.gz
$ cd $GOROOT/src
$ ## For Linux 32bit.
$ GOOS=linux GOARCH=386 ./make.bash
$ ## For Windows 64bit.
$ GOOS=windows GOARCH=amd64 ./make.bash
$ ## For Windows 32bit.
$ GOOS=windows GOARCH=386 ./make.bash
$ # Install dep, go-assets-builder.
$ go get -u github.com/golang/dep/cmd/dep
$ go get -u github.com/jessevdk/go-assets-builder
$ mkdir -p $GOPATH/src/github.com/qb0C80aE
$ cd $GOPATH/src/github.com/qb0C80aE
$ git clone https://github.com/qb0C80aE/clay.git
$ cd $GOPATH/src/github.com/qb0C80aE/clay
$ dep ensure
$ go generate -tags=prebuild ./...
$ ## For Linux 32bit.
$ CGO_ENABLED=1 GOOS=linux GOARCH=386 go build --ldflags '-extldflags "-static"' -o linux_386/clay
$ ## For Windows 64bit.
$ CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc LD=x86_64-w64-mingw32-ld GOOS=windows GOARCH=amd64 go build --ldflags '-extldflags "-static"' -o windows_amd64/clay.exe
$ ## For Windows 32bit.
$ CGO_ENABLED=1 CC=i686-w64-mingw32-gcc LD=i686-w64-mingw32-ld GOOS=windows GOARCH=386 go build --ldflags '-extldflags "-static"' -o windows_386/clay.exe

Build on Windows

For example, build Clay using MinGW.

  1. Install msys2 https://msys2.github.io/
  2. Run msys2 shell. i.e. C:\mingw64\msys2.exe
$ pacman -S mingw-w64-x86_64-gcc
$ cd $GOPATH/src/github.com/qb0C80aE/clay
$ go build

Powershell

PS> C:\msys64\usr\bin\pacman -S mingw-w64-x86_64-gcc
PS> cd $env:GOPATH/src/github.com/qb0C80aE/clay
PS> powershell { $env:PATH+=";C:\msys64\mingw64\bin"; go build }

Build as a single binary

If you want to build Clay as a single binary file including assets like files in examples, just specify CLAY_ASSET_MODE to internal, BUILD_ASSET to true, and BUILD_ASSET_SOURCE to the assets path at prebuild generation. And one more thing, please don't forget to specify CLAY_CONFIG_FILE_PATH to tell the default config file in the internal assets to Clay. This value is used at boot time as a default value.

$ CLAY_ASSET_MODE=internal BUILD_ASSET=true BUILD_ASSET_SOURCE=../examples/api_and_gui CLAY_CONFIG_FILE_PATH=examples/api_and_gui/clay_config.json go generate -tags=prebuild prebuild/generate.go
$ go build

After building the binary, you can boot Clay without any parameters, any other files.

$ ./clay

Even if you are using this single binary, you can get Clay to load external files by setting CLAY_ASSET_MODE variable to external at boot time.

Etc.

  • Clay is using dep to manage dependencies of its packages
  • The base part of Clay has been generated by apig
  • Assets in Clay will be archived by go-assets