<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.gaffer.wiki/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ericmehl</id>
	<title>Gaffer Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://www.gaffer.wiki/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ericmehl"/>
	<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/wiki/Special:Contributions/Ericmehl"/>
	<updated>2026-04-11T00:00:54Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.1</generator>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Adding_Presets_to_Global_Context_Variables&amp;diff=380</id>
		<title>Adding Presets to Global Context Variables</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Adding_Presets_to_Global_Context_Variables&amp;diff=380"/>
		<updated>2024-07-23T21:07:32Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Global context variables can be useful for ensuring a context variable is always accessible and set for the entire script. Unless it is overridden by a [https://www.gafferhq.org/documentation/1.4.8.0/Reference/NodeReference/Gaffer/ContextVariables.html ContextVariables] or  [https://www.gafferhq.org/documentation/1.4.8.0/Reference/NodeReference/Gaffer/ContextVariableTweaks.html ContextVariablesTweaks] node in the node graph, all nodes will have access to the same global context variable. There are some global context variables added by Gaffer by default when creating a new script. You can see these, and add your own, from the &amp;lt;code&amp;gt;Variables&amp;lt;/code&amp;gt; tab in the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog accessed from the &amp;lt;code&amp;gt;File.Settings&amp;lt;/code&amp;gt;menu item.&lt;br /&gt;
&lt;br /&gt;
The default user interface for a global context variable can be useful for many situations, but like all plugs in Gaffer, it is possible to customize how the plugs for global context variables are presented to the user. One such customization is adding presets for the user to choose from. This ensures only valid values can be assigned to the context variable. This guide will describe how to add presets to the widget controlling a global context variable.&lt;br /&gt;
&lt;br /&gt;
=== Adding Presets to the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; Dialog ===&lt;br /&gt;
Presets can be added to plugs in the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog by assigning metadata to the value plug for a global context variable. There are three steps to adding the needed metadata.&lt;br /&gt;
&lt;br /&gt;
==== Identify the target plug ====&lt;br /&gt;
Before we assign metadata, we need to identify which plug represents the context variable you want to add presets to. Global context variables are stored in the &amp;lt;code&amp;gt;variables&amp;lt;/code&amp;gt; child of the script node. In the Python editor, these are accessed by &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The entries in &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; are of the type &amp;lt;code&amp;gt;NameValuePlug&amp;lt;/code&amp;gt;. These plugs themselves have three child plugs: &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; plug sets the name of the context variable and the &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt; sets the value of the variable. The &amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt; plug is used to enable or disable the variable. Note that the value of &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; may be different from the name of the actual &amp;lt;code&amp;gt;NameValuePlug&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To determine which child of &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; you want to add metadata to, loop through all the children of &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; checking the value of the &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; plug until you find the variable. The corresponding &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt; child plug will be the plug we add metadata to.&lt;br /&gt;
&lt;br /&gt;
==== Set the widget type ====&lt;br /&gt;
Next we need to tell Gaffer to use a presets dropdown widget for our value plug. That is done by setting &amp;lt;code&amp;gt;plugValueWidget:type&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;quot;GafferUI.PresetsPlugValueWidget&amp;quot;&amp;lt;/code&amp;gt; : &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
Gaffer.Metadata.registerValue( variablePlug, &amp;quot;plugValueWidget:type&amp;quot;, &amp;quot;GafferUI.PresetsPlugValueWidget&amp;quot; )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Set the preset names and values ====&lt;br /&gt;
Now we add the presets themselves. This can be done in one of two ways. You can add a metadata entry starting with &amp;lt;code&amp;gt;preset:&amp;lt;/code&amp;gt; followed by the display string of your preset set to the preset value. For example, &amp;lt;code&amp;gt;Gaffer.Metadata.registerValue( variablePlug, &amp;quot;preset:Shot 1004&amp;quot;, &amp;quot;shot1004&amp;quot;)&amp;lt;/code&amp;gt;will create a preset showing in the UI as &amp;lt;code&amp;gt;Shot 1004&amp;lt;/code&amp;gt;. When the user chooses that preset, the actual value of the context variable will be &amp;lt;code&amp;gt;shot1004&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The second method sets all of the preset names and all of the values in one step each. This can be done by setting the &amp;lt;code&amp;gt;presetNames&amp;lt;/code&amp;gt; metadata entry to a Cortex string vector (&amp;lt;code&amp;gt;IECore.StringVectorData&amp;lt;/code&amp;gt;)holding all of the preset names. Setting &amp;lt;code&amp;gt;presetValues&amp;lt;/code&amp;gt; to a Cortex vector of some type, such as &amp;lt;code&amp;gt;IECoreStringVectorData&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;IECoreFloatVectorData&amp;lt;/code&amp;gt;.&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
Gaffer.Metadata.registerValue( variablePlug, &amp;quot;presetNames&amp;quot;, IECore.StringVectorData( presetNames ) )&lt;br /&gt;
Gaffer.Metadata.registerValue( variablePlug, &amp;quot;presetValues&amp;quot;, IECore.StringVectorData( presetValues ) )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Resetting the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog ====&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; UI is built once and then reused for subsequent showings. This means after adding presets, you need to force Gaffer to refresh the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog. You can force Gaffer to rebuild the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog by running the following code in the Python editor:&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
sw = GafferUI.ScriptWindow.acquire(root)&lt;br /&gt;
for window in sw.childWindows():&lt;br /&gt;
	if hasattr( window, &amp;quot;_settingsEditor&amp;quot; ) :&lt;br /&gt;
		sw.removeChild(window)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have registered the metadata for a plug in this way, it will be saved with the script so there is no need to register the metadata again.&lt;br /&gt;
&lt;br /&gt;
==== Example Script ====&lt;br /&gt;
&lt;br /&gt;
The following script is an example of all of the above steps condensed into a reusable function for adding presets for a global context variable.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Sets the preset names and values for a global context variable.&lt;br /&gt;
# `scriptNode` is the script node which you want to set global context variables for.&lt;br /&gt;
# `variableName` is the name of the variable to set presets for.&lt;br /&gt;
# `presetNames` is a list of strings to set the preset names to.&lt;br /&gt;
# `presetValues` is an `IECore.*VectorData` holding a list of preset values&lt;br /&gt;
# for each corresponding item in `presetNames`&lt;br /&gt;
def globalContextPresets( scriptNode, variableName, presetNames, presetValues ) :&lt;br /&gt;
	if len( presetNames ) != len( presetValues ) :&lt;br /&gt;
		raise ValueError( &amp;quot;`presetNames` and `presetValues` must be the same length&amp;quot; )&lt;br /&gt;
	&lt;br /&gt;
	# Find the value plug for `variableName` global context variable.&lt;br /&gt;
	variablePlug = None&lt;br /&gt;
	for p in scriptNode[&amp;quot;variables&amp;quot;] :&lt;br /&gt;
		if p[&amp;quot;name&amp;quot;].getValue() == variableName :&lt;br /&gt;
			variablePlug = p[&amp;quot;value&amp;quot;]&lt;br /&gt;
			break&lt;br /&gt;
&lt;br /&gt;
	if variablePlug is None :&lt;br /&gt;
		raise RuntimeError( &amp;quot;\&amp;quot;{}\&amp;quot; not found in global context variables&amp;quot;.format( variableName ) )&lt;br /&gt;
	&lt;br /&gt;
	# Set the widget to a presets dropdown.&lt;br /&gt;
	Gaffer.Metadata.registerValue( variablePlug, &amp;quot;plugValueWidget:type&amp;quot;, &amp;quot;GafferUI.PresetsPlugValueWidget&amp;quot; )&lt;br /&gt;
&lt;br /&gt;
	# Register the names and values.&lt;br /&gt;
	Gaffer.Metadata.registerValue( variablePlug, &amp;quot;presetNames&amp;quot;, IECore.StringVectorData( presetNames ) )&lt;br /&gt;
	Gaffer.Metadata.registerValue( variablePlug, &amp;quot;presetValues&amp;quot;, presetValues )&lt;br /&gt;
&lt;br /&gt;
	# Set the value to the first preset.&lt;br /&gt;
	variablePlug.setValue( presetValues[0] )&lt;br /&gt;
&lt;br /&gt;
	# Tell Gaffer to rebuild the `Settings` dialog.&lt;br /&gt;
	sw = GafferUI.ScriptWindow.acquire( scriptNode )&lt;br /&gt;
	for window in sw.childWindows():&lt;br /&gt;
		if hasattr( window, &amp;quot;_settingsEditor&amp;quot; ) :&lt;br /&gt;
			sw.removeChild(window)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example, to set a few presets for a global context variable named &amp;lt;code&amp;gt;shot&amp;lt;/code&amp;gt; run the script above in the Python editor, then run the line below.&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
globalContextPresets( root, &amp;quot;shot&amp;quot;, [&amp;quot;shot A&amp;quot;, &amp;quot;shot B&amp;quot;, &amp;quot;shot C&amp;quot;], IECore.StringVectorData( [ &amp;quot;shotA&amp;quot;, &amp;quot;shotB&amp;quot;, &amp;quot;shotC&amp;quot; ] ) )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding Presets to a Menu ===&lt;br /&gt;
Global context variables can also be controlled from a customized menu in Gaffer&#039;s main application menu. In a script in your &amp;lt;code&amp;gt;~/gaffer/startup/gui&amp;lt;/code&amp;gt; directory add the following code. It will add new menu item to Gaffer called &amp;lt;code&amp;gt;Shot&amp;lt;/code&amp;gt;. Each time the user opens it, it will be rebuilt by the method &amp;lt;code&amp;gt;__shotMenu()&amp;lt;/code&amp;gt;, which you can customize to populate the shot menu with shot names from any source accessible to Python such as a node in the node graph or an external database.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import functools&lt;br /&gt;
&lt;br /&gt;
import IECore&lt;br /&gt;
&lt;br /&gt;
import GafferUI&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# This will be called each time the user makes a selection from the `Shot` menu.&lt;br /&gt;
def __setShot( shotPlug, shot, checked ) :&lt;br /&gt;
    if shotPlug is not None :&lt;br /&gt;
        shotPlug.setValue( shot )&lt;br /&gt;
&lt;br /&gt;
# This will be called for each menu item when showing the menu. It should return `True`&lt;br /&gt;
# if it should be checked and `False` if it should not be.&lt;br /&gt;
def __activeShot( shotPlug, shot ) :&lt;br /&gt;
    if shotPlug is not None :&lt;br /&gt;
        return shotPlug.getValue() == shot&lt;br /&gt;
&lt;br /&gt;
# This will be called each time the user opens the `Shot` menu. It should return an&lt;br /&gt;
# `IECore.MenuDefinition` object representing the menu.&lt;br /&gt;
def __shotMenu( menu ) :&lt;br /&gt;
    globalContextVariable = &amp;quot;shot&amp;quot;&lt;br /&gt;
    # Populate the menu with placeholder item if no plug is found for `globalContextVariable`&lt;br /&gt;
    defaultItems = [ &amp;quot;None&amp;quot; ]&lt;br /&gt;
&lt;br /&gt;
    scriptWindow = menu.ancestor(GafferUI.ScriptWindow)&lt;br /&gt;
    currentScript = scriptWindow.scriptNode()&lt;br /&gt;
&lt;br /&gt;
    # Find the plug for the value of the global context variable.&lt;br /&gt;
    shotPlug = None&lt;br /&gt;
    for p in currentScript[&amp;quot;variables&amp;quot;] :&lt;br /&gt;
        if p[&amp;quot;name&amp;quot;].getValue() == globalContextVariable :&lt;br /&gt;
            shotPlug = p[&amp;quot;value&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
    result = IECore.MenuDefinition()&lt;br /&gt;
&lt;br /&gt;
    if shotPlug is None :&lt;br /&gt;
       shotList = defaultItems&lt;br /&gt;
    else :&lt;br /&gt;
        # Hardcoded shot list&lt;br /&gt;
        shotList = [&amp;quot;shotA&amp;quot;, &amp;quot;shotB&amp;quot;, &amp;quot;shotC&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
        # Shot list from the enabled rows of a spreadsheet named &amp;quot;shots&amp;quot;&lt;br /&gt;
        # shotList = currentScript[&amp;quot;shots&amp;quot;][&amp;quot;enabledRowNames&amp;quot;].getValue()&lt;br /&gt;
&lt;br /&gt;
    # Add a shot for each item in `shotList`. When selecting the item, the `__setShot()`&lt;br /&gt;
    # function will be called with the the `shotPlug`, the `shot` value from the loop&lt;br /&gt;
    # and a `checked` variable the Gaffer menu system adds.&lt;br /&gt;
    # When determining if the item should have a checkmark next to it, `__activeShot()` will&lt;br /&gt;
    # be called with the `shotPlug` and `shot` value from the loop.&lt;br /&gt;
    for shot in shotList :&lt;br /&gt;
        result.append(&lt;br /&gt;
            &amp;quot;/&amp;quot; + shot,&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;command&amp;quot;: functools.partial( __setShot, shotPlug, shot ) ,&lt;br /&gt;
                &amp;quot;checkBox&amp;quot;: functools.partial( __activeShot, shotPlug, shot ),&lt;br /&gt;
            }&lt;br /&gt;
        )&lt;br /&gt;
&lt;br /&gt;
    return result&lt;br /&gt;
&lt;br /&gt;
# Called once at the start of a Gaffer session. Note that this will not be called&lt;br /&gt;
# on subsequent loading of a script, since the newly created window will be in the same session.&lt;br /&gt;
scriptWindowMenu = GafferUI.ScriptWindow.menuDefinition( application )&lt;br /&gt;
scriptWindowMenu.append( &amp;quot;/Shot&amp;quot;, { &amp;quot;subMenu&amp;quot;: __shotMenu } )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Adding_Presets_to_Global_Context_Variables&amp;diff=379</id>
		<title>Adding Presets to Global Context Variables</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Adding_Presets_to_Global_Context_Variables&amp;diff=379"/>
		<updated>2024-07-23T21:00:55Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Global context variables can be useful for ensuring a context variable is always accessible and set for the entire script. Unless it is overridden by a [https://www.gafferhq.org/documentation/1.4.8.0/Reference/NodeReference/Gaffer/ContextVariables.html ContextVariables] or  [https://www.gafferhq.org/documentation/1.4.8.0/Reference/NodeReference/Gaffer/ContextVariableTweaks.html ContextVariablesTweaks] node in the node graph, all nodes will have access to the same global context variable. There are some global context variables added by Gaffer by default when creating a new script. You can see these, and add your own, from the &amp;lt;code&amp;gt;Variables&amp;lt;/code&amp;gt; tab in the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog accessed from the &amp;lt;code&amp;gt;File.Settings&amp;lt;/code&amp;gt;menu item.&lt;br /&gt;
&lt;br /&gt;
The default user interface for a global context variable can be useful for many situations, but like all plugs in Gaffer, it is possible to customize how the plugs for global context variables are presented to the user. One such customization is adding presets for the user to choose from. This ensures only valid values can be assigned to the context variable. This guide will describe how to add presets to the widget controlling a global context variable.&lt;br /&gt;
&lt;br /&gt;
=== Adding Presets to the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; Dialog ===&lt;br /&gt;
Presets can be added to plugs in the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog by assigning metadata to the value plug for a global context variable. There are three steps to adding the needed metadata.&lt;br /&gt;
&lt;br /&gt;
==== Identify the target plug ====&lt;br /&gt;
Before we assign metadata, we need to identify which plug represents the context variable you want to add presets to. Global context variables are stored in the &amp;lt;code&amp;gt;variables&amp;lt;/code&amp;gt; child of the script node. In the Python editor, these are accessed by &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The entries in &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; are of the type &amp;lt;code&amp;gt;NameValuePlug&amp;lt;/code&amp;gt;. These plugs themselves have three child plugs: &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; plug sets the name of the context variable and the &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt; sets the value of the variable. The &amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt; plug is used to enable or disable the variable. Note that the value of &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; may be different from the name of the actual &amp;lt;code&amp;gt;NameValuePlug&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To determine which child of &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; you want to add metadata to, loop through all the children of &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; checking the value of the &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; plug until you find the variable. The corresponding &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt; child plug will be the plug we add metadata to.&lt;br /&gt;
&lt;br /&gt;
==== Set the widget type ====&lt;br /&gt;
Next we need to tell Gaffer to use a presets dropdown widget for our value plug. That is done by setting &amp;lt;code&amp;gt;plugValueWidget:type&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;quot;GafferUI.PresetsPlugValueWidget&amp;quot;&amp;lt;/code&amp;gt; : &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
Gaffer.Metadata.registerValue( variablePlug, &amp;quot;plugValueWidget:type&amp;quot;, &amp;quot;GafferUI.PresetsPlugValueWidget&amp;quot; )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Set the preset names and values ====&lt;br /&gt;
Now we add the presets themselves. This can be done in one of two ways. You can add a metadata entry starting with &amp;lt;code&amp;gt;preset:&amp;lt;/code&amp;gt; followed by the display string of your preset set to the preset value. For example, &amp;lt;code&amp;gt;Gaffer.Metadata.registerValue( variablePlug, &amp;quot;preset:Shot 1004&amp;quot;, &amp;quot;shot1004&amp;quot;)&amp;lt;/code&amp;gt;will create a preset showing in the UI as &amp;lt;code&amp;gt;Shot 1004&amp;lt;/code&amp;gt;. When the user chooses that preset, the actual value of the context variable will be &amp;lt;code&amp;gt;shot1004&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The second method sets all of the preset names and all of the values in one step each. This can be done by setting the &amp;lt;code&amp;gt;presetNames&amp;lt;/code&amp;gt; metadata entry to a Cortex string vector (&amp;lt;code&amp;gt;IECore.StringVectorData&amp;lt;/code&amp;gt;)holding all of the preset names. Setting &amp;lt;code&amp;gt;presetValues&amp;lt;/code&amp;gt; to a Cortex vector of some type, such as &amp;lt;code&amp;gt;IECoreStringVectorData&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;IECoreFloatVectorData&amp;lt;/code&amp;gt;.&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
Gaffer.Metadata.registerValue( variablePlug, &amp;quot;presetNames&amp;quot;, IECore.StringVectorData( presetNames ) )&lt;br /&gt;
Gaffer.Metadata.registerValue( variablePlug, &amp;quot;presetValues&amp;quot;, IECore.StringVectorData( presetValues ) )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Resetting the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog ====&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; UI is built once and then reused for subsequent showings. This means after adding presets, you need to force Gaffer to refresh the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog. You can force Gaffer to rebuild the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog by running the following code in the Python editor:&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
sw = GafferUI.ScriptWindow.acquire(root)&lt;br /&gt;
for window in sw.childWindows():&lt;br /&gt;
	if hasattr( window, &amp;quot;_settingsEditor&amp;quot; ) :&lt;br /&gt;
		sw.removeChild(window)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have registered the metadata for a plug in this way, it will be saved with the script so there is no need to register the metadata again.&lt;br /&gt;
&lt;br /&gt;
==== Example Script ====&lt;br /&gt;
&lt;br /&gt;
The following script is an example of all of the above steps condensed into a reusable function for adding presets for a global context variable.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Sets the preset names and values for a global context variable.&lt;br /&gt;
# `scriptNode` is the script node which you want to set global context variables for.&lt;br /&gt;
# `variableName` is the name of the variable to set presets for.&lt;br /&gt;
# `presetNames` is a list of strings to set the preset names to.&lt;br /&gt;
# `presetValues` is an `IECore.*VectorData` holding a list of preset values&lt;br /&gt;
# for each corresponding item in `presetNames`&lt;br /&gt;
def globalContextPresets( scriptNode, variableName, presetNames, presetValues ) :&lt;br /&gt;
	if len( presetNames ) != len( presetValues ) :&lt;br /&gt;
		raise ValueError( &amp;quot;`presetNames` and `presetValues` must be the same length&amp;quot; )&lt;br /&gt;
	&lt;br /&gt;
	# Find the value plug for `variableName` global context variable.&lt;br /&gt;
	variablePlug = None&lt;br /&gt;
	for p in scriptNode[&amp;quot;variables&amp;quot;] :&lt;br /&gt;
		if p[&amp;quot;name&amp;quot;].getValue() == variableName :&lt;br /&gt;
			variablePlug = p[&amp;quot;value&amp;quot;]&lt;br /&gt;
			break&lt;br /&gt;
&lt;br /&gt;
	if variablePlug is None :&lt;br /&gt;
		raise RuntimeError( &amp;quot;\&amp;quot;{}\&amp;quot; not found in global context variables&amp;quot;.format( variableName ) )&lt;br /&gt;
	&lt;br /&gt;
	# Set the widget to a presets dropdown.&lt;br /&gt;
	Gaffer.Metadata.registerValue( variablePlug, &amp;quot;plugValueWidget:type&amp;quot;, &amp;quot;GafferUI.PresetsPlugValueWidget&amp;quot; )&lt;br /&gt;
&lt;br /&gt;
	# Register the names and values.&lt;br /&gt;
	Gaffer.Metadata.registerValue( variablePlug, &amp;quot;presetNames&amp;quot;, IECore.StringVectorData( presetNames ) )&lt;br /&gt;
	Gaffer.Metadata.registerValue( variablePlug, &amp;quot;presetValues&amp;quot;, presetValues )&lt;br /&gt;
&lt;br /&gt;
	# Set the value to the first preset.&lt;br /&gt;
	variablePlug.setValue( presetValues[0] )&lt;br /&gt;
&lt;br /&gt;
	# Tell Gaffer to rebuild the `Settings` dialog.&lt;br /&gt;
	sw = GafferUI.ScriptWindow.acquire( scriptNode )&lt;br /&gt;
	for window in sw.childWindows():&lt;br /&gt;
		if hasattr( window, &amp;quot;_settingsEditor&amp;quot; ) :&lt;br /&gt;
			sw.removeChild(window)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example, to set a few presets for a global context variable named &amp;lt;code&amp;gt;shot&amp;lt;/code&amp;gt; run the script above in the Python editor, then run the line below.&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
globalContextPresets( root, &amp;quot;shot&amp;quot;, [&amp;quot;shot A&amp;quot;, &amp;quot;shot B&amp;quot;, &amp;quot;shot C&amp;quot;], IECore.StringVectorData( [ &amp;quot;shotA&amp;quot;, &amp;quot;shotB&amp;quot;, &amp;quot;shotC&amp;quot; ] ) )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding Presets to a Menu ===&lt;br /&gt;
Global context variables can also be controlled from a customized menu in Gaffer&#039;s main application menu. In a script in your &amp;lt;code&amp;gt;~/gaffer/startup/gui&amp;lt;/code&amp;gt; directory add the following code. It will add new menu item to Gaffer called &amp;lt;code&amp;gt;Shot&amp;lt;/code&amp;gt;. Each time the user opens it, it will be rebuilt by the method `__shotMenu()`, which you can customize to populate the shot menu with shot names from any source accessible to Python such as a node in the node graph or an external database.&amp;lt;pre&amp;gt;&lt;br /&gt;
import functools&lt;br /&gt;
&lt;br /&gt;
import IECore&lt;br /&gt;
&lt;br /&gt;
import GafferUI&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# This will be called each time the user makes a selection from the `Shot` menu.&lt;br /&gt;
def __setShot( shotPlug, shot, checked ) :&lt;br /&gt;
    if shotPlug is not None :&lt;br /&gt;
        shotPlug.setValue( shot )&lt;br /&gt;
&lt;br /&gt;
# This will be called for each menu item when showing the menu. It should return `True`&lt;br /&gt;
# if it should be checked and `False` if it should not be.&lt;br /&gt;
def __activeShot( shotPlug, shot ) :&lt;br /&gt;
    if shotPlug is not None :&lt;br /&gt;
        return shotPlug.getValue() == shot&lt;br /&gt;
&lt;br /&gt;
# This will be called each time the user opens the `Shot` menu. It should return an&lt;br /&gt;
# `IECore.MenuDefinition` object representing the menu.&lt;br /&gt;
def __shotMenu( menu ) :&lt;br /&gt;
    globalContextVariable = &amp;quot;shot&amp;quot;&lt;br /&gt;
    # Populate the menu with placeholder item if no plug is found for `globalContextVariable`&lt;br /&gt;
    defaultItems = [ &amp;quot;None&amp;quot; ]&lt;br /&gt;
&lt;br /&gt;
    scriptWindow = menu.ancestor(GafferUI.ScriptWindow)&lt;br /&gt;
    currentScript = scriptWindow.scriptNode()&lt;br /&gt;
&lt;br /&gt;
    # Find the plug for the value of the global context variable.&lt;br /&gt;
    shotPlug = None&lt;br /&gt;
    for p in currentScript[&amp;quot;variables&amp;quot;] :&lt;br /&gt;
        if p[&amp;quot;name&amp;quot;].getValue() == globalContextVariable :&lt;br /&gt;
            shotPlug = p[&amp;quot;value&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
    result = IECore.MenuDefinition()&lt;br /&gt;
&lt;br /&gt;
    if shotPlug is None :&lt;br /&gt;
       shotList = defaultItems&lt;br /&gt;
    else :&lt;br /&gt;
        # Hardcoded shot list&lt;br /&gt;
        shotList = [&amp;quot;shotA&amp;quot;, &amp;quot;shotB&amp;quot;, &amp;quot;shotC&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
        # Shot list from the enabled rows of a spreadsheet named &amp;quot;shots&amp;quot;&lt;br /&gt;
        # shotList = currentScript[&amp;quot;shots&amp;quot;][&amp;quot;enabledRowNames&amp;quot;].getValue()&lt;br /&gt;
&lt;br /&gt;
    # Add a shot for each item in `shotList`. When selecting the item, the `__setShot()`&lt;br /&gt;
    # function will be called with the the `shotPlug`, the `shot` value from the loop&lt;br /&gt;
    # and a `checked` variable the Gaffer menu system adds.&lt;br /&gt;
    # When determining if the item should have a checkmark next to it, `__activeShot()` will&lt;br /&gt;
    # be called with the `shotPlug` and `shot` value from the loop.&lt;br /&gt;
    for shot in shotList :&lt;br /&gt;
        result.append(&lt;br /&gt;
            &amp;quot;/&amp;quot; + shot,&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;command&amp;quot;: functools.partial( __setShot, shotPlug, shot ) ,&lt;br /&gt;
                &amp;quot;checkBox&amp;quot;: functools.partial( __activeShot, shotPlug, shot ),&lt;br /&gt;
            }&lt;br /&gt;
        )&lt;br /&gt;
&lt;br /&gt;
    return result&lt;br /&gt;
&lt;br /&gt;
# Called once at the start of a Gaffer session. Note that this will not be called&lt;br /&gt;
# on subsequent loading of a script, since the newly created window will be in the same session.&lt;br /&gt;
scriptWindowMenu = GafferUI.ScriptWindow.menuDefinition( application )&lt;br /&gt;
scriptWindowMenu.append( &amp;quot;/Shot&amp;quot;, { &amp;quot;subMenu&amp;quot;: __shotMenu } )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Adding_Presets_to_Global_Context_Variables&amp;diff=360</id>
		<title>Adding Presets to Global Context Variables</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Adding_Presets_to_Global_Context_Variables&amp;diff=360"/>
		<updated>2024-07-19T20:35:14Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Global context variables can be useful for ensuring a context variable is always accessible and set for the entire script. Unless it is overridden by a [https://www.gafferhq.org/documentation/1.4.8.0/Reference/NodeReference/Gaffer/ContextVariables.html ContextVariables] or  [https://www.gafferhq.org/documentation/1.4.8.0/Reference/NodeReference/Gaffer/ContextVariableTweaks.html ContextVariablesTweaks] node in the node graph, all nodes will have access to the same global context variable. There are some global context variables added by Gaffer by default when creating a new script. You can see these, and add your own, from the &amp;lt;code&amp;gt;Variables&amp;lt;/code&amp;gt; tab in the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog accessed from the &amp;lt;code&amp;gt;File.Settings&amp;lt;/code&amp;gt;menu item.&lt;br /&gt;
&lt;br /&gt;
The default user interface for a global context variable can be useful for many situations, but like all plugs in Gaffer, it is possible to customize how the plugs for global context variables are presented to the user. One such customization is adding presets for the user to choose from. This ensures only valid values can be assigned to the context variable. This guide will describe how to add presets to the widget controlling a global context variable.&lt;br /&gt;
&lt;br /&gt;
=== Adding Presets to the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; Dialog ===&lt;br /&gt;
Presets can be added to plugs in the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog by assigning metadata to the value plug for a global context variable. There are three steps to adding the needed metadata.&lt;br /&gt;
&lt;br /&gt;
==== Identify the target plug ====&lt;br /&gt;
Before we assign metadata, we need to identify which plug represents the context variable you want to add presets to. Global context variables are stored in the &amp;lt;code&amp;gt;variables&amp;lt;/code&amp;gt; child of the script node. In the Python editor, these are accessed by &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The entries in &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; are of the type &amp;lt;code&amp;gt;NameValuePlug&amp;lt;/code&amp;gt;. These plugs themselves have three child plugs: &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; plug sets the name of the context variable and the &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt; sets the value of the variable. The &amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt; plug is used to enable or disable the variable. Note that the value of &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; may be different from the name of the actual &amp;lt;code&amp;gt;NameValuePlug&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To determine which child of &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; you want to add metadata to, loop through all the children of &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; checking the value of the &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; plug until you find the variable. The corresponding &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt; child plug will be the plug we add metadata to.&lt;br /&gt;
&lt;br /&gt;
==== Set the widget type ====&lt;br /&gt;
Next we need to tell Gaffer to use a presets dropdown widget for our value plug. That is done by setting &amp;lt;code&amp;gt;plugValueWidget:type&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;quot;GafferUI.PresetsPlugValueWidget&amp;quot;&amp;lt;/code&amp;gt; : &amp;lt;pre&amp;gt;&lt;br /&gt;
Gaffer.Metadata.registerValue( variablePlug, &amp;quot;plugValueWidget:type&amp;quot;, &amp;quot;GafferUI.PresetsPlugValueWidget&amp;quot; )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Set the preset names and values ====&lt;br /&gt;
Now we add the presets themselves. This can be done in one of two ways. You can add a metadata entry starting with &amp;lt;code&amp;gt;preset:&amp;lt;/code&amp;gt; followed by the display string of your preset set to the preset value. For example, &amp;lt;code&amp;gt;Gaffer.Metadata.registerValue( variablePlug, &amp;quot;preset:Shot 1004&amp;quot;, &amp;quot;shot1004&amp;quot;)&amp;lt;/code&amp;gt;will create a preset showing in the UI as &amp;lt;code&amp;gt;Shot 1004&amp;lt;/code&amp;gt;. When the user chooses that preset, the actual value of the context variable will be &amp;lt;code&amp;gt;shot1004&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The second method sets all of the preset names and all of the values in one step each. This can be done by setting the &amp;lt;code&amp;gt;presetNames&amp;lt;/code&amp;gt; metadata entry to a Cortex string vector (&amp;lt;code&amp;gt;IECore.StringVectorData&amp;lt;/code&amp;gt;)holding all of the preset names. Setting &amp;lt;code&amp;gt;presetValues&amp;lt;/code&amp;gt; to a Cortex vector of some type, such as &amp;lt;code&amp;gt;IECoreStringVectorData&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;IECoreFloatVectorData&amp;lt;/code&amp;gt;.&amp;lt;pre&amp;gt;&lt;br /&gt;
Gaffer.Metadata.registerValue( variablePlug, &amp;quot;presetNames&amp;quot;, IECore.StringVectorData( presetNames ) )&lt;br /&gt;
Gaffer.Metadata.registerValue( variablePlug, &amp;quot;presetValues&amp;quot;, IECore.StringVectorData( presetValues ) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Resetting the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog ====&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; UI is built once and then reused for subsequent showings. This means after adding presets, you need to force Gaffer to refresh the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog. You can force Gaffer to rebuild the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog by running the following code in the Python editor:&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = GafferUI.ScriptWindow.acquire(root)&lt;br /&gt;
for window in sw.childWindows():&lt;br /&gt;
	if hasattr( window, &amp;quot;_settingsEditor&amp;quot; ) :&lt;br /&gt;
		sw.removeChild(window)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have registered the metadata for a plug in this way, it will be saved with the script so there is no need to register the metadata again.&lt;br /&gt;
&lt;br /&gt;
==== Example Script ====&lt;br /&gt;
&lt;br /&gt;
The following script is an example of all of the above steps condensed into a reusable function for adding presets for a global context variable.&amp;lt;pre&amp;gt;&lt;br /&gt;
# Sets the preset names and values for a global context variable.&lt;br /&gt;
# `scriptNode` is the script node which you want to set global context variables for.&lt;br /&gt;
# `variableName` is the name of the variable to set presets for.&lt;br /&gt;
# `presetNames` is a list of strings to set the preset names to.&lt;br /&gt;
# `presetValues` is an `IECore.*VectorData` holding a list of preset values&lt;br /&gt;
# for each corresponding item in `presetNames`&lt;br /&gt;
def globalContextPresets( scriptNode, variableName, presetNames, presetValues ) :&lt;br /&gt;
	if len( presetNames ) != len( presetValues ) :&lt;br /&gt;
		raise ValueError( &amp;quot;`presetNames` and `presetValues` must be the same length&amp;quot; )&lt;br /&gt;
	&lt;br /&gt;
	# Find the value plug for `variableName` global context variable.&lt;br /&gt;
	variablePlug = None&lt;br /&gt;
	for p in scriptNode[&amp;quot;variables&amp;quot;] :&lt;br /&gt;
		if p[&amp;quot;name&amp;quot;].getValue() == variableName :&lt;br /&gt;
			variablePlug = p[&amp;quot;value&amp;quot;]&lt;br /&gt;
			break&lt;br /&gt;
&lt;br /&gt;
	if variablePlug is None :&lt;br /&gt;
		raise RuntimeError( &amp;quot;\&amp;quot;{}\&amp;quot; not found in global context variables&amp;quot;.format( variableName ) )&lt;br /&gt;
	&lt;br /&gt;
	# Set the widget to a presets dropdown.&lt;br /&gt;
	Gaffer.Metadata.registerValue( variablePlug, &amp;quot;plugValueWidget:type&amp;quot;, &amp;quot;GafferUI.PresetsPlugValueWidget&amp;quot; )&lt;br /&gt;
&lt;br /&gt;
	# Register the names and values.&lt;br /&gt;
	Gaffer.Metadata.registerValue( variablePlug, &amp;quot;presetNames&amp;quot;, IECore.StringVectorData( presetNames ) )&lt;br /&gt;
	Gaffer.Metadata.registerValue( variablePlug, &amp;quot;presetValues&amp;quot;, presetValues )&lt;br /&gt;
&lt;br /&gt;
	# Set the value to the first preset.&lt;br /&gt;
	variablePlug.setValue( presetValues[0] )&lt;br /&gt;
&lt;br /&gt;
	# Tell Gaffer to rebuild the `Settings` dialog.&lt;br /&gt;
	sw = GafferUI.ScriptWindow.acquire( scriptNode )&lt;br /&gt;
	for window in sw.childWindows():&lt;br /&gt;
		if hasattr( window, &amp;quot;_settingsEditor&amp;quot; ) :&lt;br /&gt;
			sw.removeChild(window)&lt;br /&gt;
&amp;lt;/pre&amp;gt;For example, to set a few presets for a global context variable named &amp;lt;code&amp;gt;shot&amp;lt;/code&amp;gt; run the script above in the Python editor, then run the line below.&amp;lt;pre&amp;gt;&lt;br /&gt;
globalContextPresets( root, &amp;quot;shot&amp;quot;, [&amp;quot;shot A&amp;quot;, &amp;quot;shot B&amp;quot;, &amp;quot;shot C&amp;quot;], IECore.StringVectorData( [ &amp;quot;shotA&amp;quot;, &amp;quot;shotB&amp;quot;, &amp;quot;shotC&amp;quot; ] ) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Adding_Presets_to_Global_Context_Variables&amp;diff=359</id>
		<title>Adding Presets to Global Context Variables</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Adding_Presets_to_Global_Context_Variables&amp;diff=359"/>
		<updated>2024-07-19T20:19:13Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Global context variables can be useful for ensuring a context variable is always accessible and set for the entire script. Unless it is overridden by a [https://www.gafferhq.org/documentation/1.4.8.0/Reference/NodeReference/Gaffer/ContextVariables.html ContextVariables] or  [https://www.gafferhq.org/documentation/1.4.8.0/Reference/NodeReference/Gaffer/ContextVariableTweaks.html ContextVariablesTweaks] node in the node graph, all nodes will have access to the same global context variable. There are some global context variables added by Gaffer by default when creating a new script. You can see these, and add your own, from the &amp;lt;code&amp;gt;Variables&amp;lt;/code&amp;gt; tab in the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog accessed from the &amp;lt;code&amp;gt;File.Settings&amp;lt;/code&amp;gt;menu item.&lt;br /&gt;
&lt;br /&gt;
The default user interface for a global context variable can be useful for many situations, but like all plugs in Gaffer, it is possible to customize how the plugs for global context variables are presented to the user. One such customization is adding presets for the user to choose from. This ensures only valid values can be assigned to the context variable. This guide will describe how to add presets to the widget controlling a global context variable.&lt;br /&gt;
&lt;br /&gt;
=== Adding Presets to the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; Dialog ===&lt;br /&gt;
One way of controlling global context variables is through the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog as described above. Presets can be added here by assigning metadata to the value plug for a global context variable. Before we assign metadata, we need to identify which plug represents the context variable you want to add presets to. Global context variables are stored in the &amp;lt;code&amp;gt;variables&amp;lt;/code&amp;gt; child of the script root. In the Python editor, these are accessed by &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The entries in &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; are of the type &amp;lt;code&amp;gt;NameValuePlug&amp;lt;/code&amp;gt;. These plugs themselves have three child plugs : &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; plug sets the name of the context variable and the &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt; sets the value of the variable. The &amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt; plug is used to enable or disable the variable. Note that the value of &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; may be different from the name of the actual &amp;lt;code&amp;gt;NameValuePlug&amp;lt;/code&amp;gt;. When adding plugs in using the &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; button in the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog, the &amp;lt;code&amp;gt;NameValuePlug&amp;lt;/code&amp;gt; added will start with &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; and be followed by the next available number to keep the child names of &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; unique.&lt;br /&gt;
&lt;br /&gt;
To determine which child of &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; you want to add metadata to, loop through all the children of &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; checking the value of the &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; plug until you find the variable. The corresponding &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt; child plug will be the plug we add metadata to.&lt;br /&gt;
&lt;br /&gt;
The first metadata entry will tell Gaffer to use a presets dropdown as the plug widget. That is done by setting &amp;lt;code&amp;gt;plugValueWidget:type&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;quot;GafferUI.PresetsPlugValueWidget&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now we can add the presets themselves. That can be done in one of two ways. You can add a metadata entry starting with &amp;lt;code&amp;gt;preset:&amp;lt;/code&amp;gt; followed by the display string of your preset, the value of which is the preset value. For example, &amp;lt;code&amp;gt;Gaffer.Metadata.registerValue( root[&amp;quot;variables&amp;quot;][&amp;quot;member1&amp;quot;][&amp;quot;value&amp;quot;], &amp;quot;preset:Shot 1004&amp;quot;, &amp;quot;shot1004&amp;quot;)&amp;lt;/code&amp;gt;will create a preset on the &amp;lt;code&amp;gt;member1&amp;lt;/code&amp;gt; plug&#039;s &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt; plug called &amp;lt;code&amp;gt;Shot 1004&amp;lt;/code&amp;gt;. When the user chooses that preset, the actual value of the context variable will be &amp;lt;code&amp;gt;shot1004&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The second method sets all of the preset names and all of the values in one step each. This can be done by setting the &amp;lt;code&amp;gt;presetNames&amp;lt;/code&amp;gt; metadata entry to a Cortex string vector (&amp;lt;code&amp;gt;IECore.StringVectorData&amp;lt;/code&amp;gt;)holding all of the preset names. Setting &amp;lt;code&amp;gt;presetValues&amp;lt;/code&amp;gt; to a Cortex vector of some type, such as &amp;lt;code&amp;gt;IECoreStringVectorData&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;IECoreFloatVectorData&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; UI is built once and then reused for subsequent showings. This means after adding presets, you need to force Gaffer to refresh the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog. You can force Gaffer to rebuild the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog by running the following code in the Python editor :&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = GafferUI.ScriptWindow.acquire(root)&lt;br /&gt;
for window in sw.childWindows():&lt;br /&gt;
	if hasattr( window, &amp;quot;_settingsEditor&amp;quot; ) :&lt;br /&gt;
		sw.removeChild(window)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following script is an example of all of the above steps condensed into a reusable function for adding presets for a global context variable.&amp;lt;pre&amp;gt;&lt;br /&gt;
# Sets the preset names and values for a global context variable.&lt;br /&gt;
# `scriptNode` is the script node which you want to set global context variables for.&lt;br /&gt;
# `variableName` is the name of the variable to set presets for.&lt;br /&gt;
# `presetNames` is a list of strings to set the preset names to.&lt;br /&gt;
# `presetValues` is an `IECore.*VectorData` holding a list of preset values&lt;br /&gt;
# for each corresponding item in `presetNames`&lt;br /&gt;
def globalContextPresets( scriptNode, variableName, presetNames, presetValues ) :&lt;br /&gt;
	if len( presetNames ) != len( presetValues ) :&lt;br /&gt;
		raise ValueError( &amp;quot;`presetNames` and `presetValues` must be the same length&amp;quot; )&lt;br /&gt;
	&lt;br /&gt;
	# Find the value plug for `variableName` global context variable.&lt;br /&gt;
	variablePlug = None&lt;br /&gt;
	for p in scriptNode[&amp;quot;variables&amp;quot;] :&lt;br /&gt;
		if p[&amp;quot;name&amp;quot;].getValue() == variableName :&lt;br /&gt;
			variablePlug = p[&amp;quot;value&amp;quot;]&lt;br /&gt;
			break&lt;br /&gt;
&lt;br /&gt;
	if variablePlug is None :&lt;br /&gt;
		raise RuntimeError( &amp;quot;\&amp;quot;{}\&amp;quot; not found in global context variables&amp;quot;.format( variableName ) )&lt;br /&gt;
	&lt;br /&gt;
	# Set the widget to a presets dropdown.&lt;br /&gt;
	Gaffer.Metadata.registerValue( variablePlug, &amp;quot;plugValueWidget:type&amp;quot;, &amp;quot;GafferUI.PresetsPlugValueWidget&amp;quot; )&lt;br /&gt;
&lt;br /&gt;
	# Register the names and values.&lt;br /&gt;
	Gaffer.Metadata.registerValue( variablePlug, &amp;quot;presetNames&amp;quot;, IECore.StringVectorData( presetNames ) )&lt;br /&gt;
	Gaffer.Metadata.registerValue( variablePlug, &amp;quot;presetValues&amp;quot;, presetValues )&lt;br /&gt;
&lt;br /&gt;
	# Set the value to the first preset.&lt;br /&gt;
	variablePlug.setValue( presetValues[0] )&lt;br /&gt;
&lt;br /&gt;
	# Tell Gaffer to rebuild the `Settings` dialog.&lt;br /&gt;
	sw = GafferUI.ScriptWindow.acquire( scriptNode )&lt;br /&gt;
	for window in sw.childWindows():&lt;br /&gt;
		if hasattr( window, &amp;quot;_settingsEditor&amp;quot; ) :&lt;br /&gt;
			sw.removeChild(window)&lt;br /&gt;
&amp;lt;/pre&amp;gt;For example, to set a few presets for a global context variable named &amp;lt;code&amp;gt;shot&amp;lt;/code&amp;gt; run the script above in the Python editor, followed by the line below.&amp;lt;pre&amp;gt;&lt;br /&gt;
globalContextPresets( root, &amp;quot;shot&amp;quot;, [&amp;quot;shot A&amp;quot;, &amp;quot;shot B&amp;quot;, &amp;quot;shot C&amp;quot;], IECore.StringVectorData( [ &amp;quot;shotA&amp;quot;, &amp;quot;shotB&amp;quot;, &amp;quot;shotC&amp;quot; ] ) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Adding_Presets_to_Global_Context_Variables&amp;diff=358</id>
		<title>Adding Presets to Global Context Variables</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Adding_Presets_to_Global_Context_Variables&amp;diff=358"/>
		<updated>2024-07-19T20:01:51Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Global context variables can be useful for ensuring a context variable is always accessible and set for the entire script. Unless it is overridden by a [https://www.gafferhq.org/documentation/1.4.8.0/Reference/NodeReference/Gaffer/ContextVariables.html ContextVariables] or  [https://www.gafferhq.org/documentation/1.4.8.0/Reference/NodeReference/Gaffer/ContextVariableTweaks.html ContextVariablesTweaks] node in the node graph, all nodes will have access to the same global context variable. There are some global context variables added by Gaffer by default when creating a new script. You can see these, and add your own, from the &amp;lt;code&amp;gt;Variables&amp;lt;/code&amp;gt; tab in the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog accessed from the &amp;lt;code&amp;gt;File.Settings&amp;lt;/code&amp;gt;menu item.&lt;br /&gt;
&lt;br /&gt;
The default user interface for a global context variable can be useful for many situations, but like all plugs in Gaffer, it is possible to customize how the plugs for global context variables are presented to the user. One such customization is adding presets for the user to choose from. This ensures only valid values can be assigned to the context variable. This guide will describe how to add presets to the widget controlling a global context variable.&lt;br /&gt;
&lt;br /&gt;
=== Adding Presets to the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; Dialog ===&lt;br /&gt;
One way of controlling global context variables is through the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog as described above. Presets can be added here by assigning metadata to the value plug for a global context variable. Before we assign metadata, we need to identify which plug represents the context variable you want to add presets to. Global context variables are stored in the &amp;lt;code&amp;gt;variables&amp;lt;/code&amp;gt; child of the script root. In the Python editor, these are accessed by &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The entries in &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; are of the type &amp;lt;code&amp;gt;NameValuePlug&amp;lt;/code&amp;gt;. These plugs themselves have three child plugs : &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; plug sets the name of the context variable and the &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt; sets the value of the variable. The &amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt; plug is used to enable or disable the variable. Note that the value of &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; may be different from the name of the actual &amp;lt;code&amp;gt;NameValuePlug&amp;lt;/code&amp;gt;. When adding plugs in using the &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; button in the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog, the &amp;lt;code&amp;gt;NameValuePlug&amp;lt;/code&amp;gt; added will start with &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; and be followed by the next available number to keep the child names of &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; unique.&lt;br /&gt;
&lt;br /&gt;
To determine which child of &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; you want to add metadata to, loop through all the children of &amp;lt;code&amp;gt;root[&amp;quot;variables&amp;quot;]&amp;lt;/code&amp;gt; checking the value of the &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; plug until you find the variable. The corresponding &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt; child plug will be the plug we add metadata to.&lt;br /&gt;
&lt;br /&gt;
The first metadata entry will tell Gaffer to use a presets dropdown as the plug widget. That is done by setting &amp;lt;code&amp;gt;plugValueWidget:type&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;quot;GafferUI.PresetsPlugValueWidget&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now we can add the presets themselves. That can be done in one of two ways. You can add a metadata entry starting with &amp;lt;code&amp;gt;preset:&amp;lt;/code&amp;gt; followed by the display string of your preset, the value of which is the preset value. For example, &amp;lt;code&amp;gt;Gaffer.Metadata.registerValue( root[&amp;quot;variables&amp;quot;][&amp;quot;member1&amp;quot;][&amp;quot;value&amp;quot;], &amp;quot;preset:Shot 1004&amp;quot;, &amp;quot;shot1004&amp;quot;)&amp;lt;/code&amp;gt;will create a preset on the &amp;lt;code&amp;gt;member1&amp;lt;/code&amp;gt; plug&#039;s &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt; plug called &amp;lt;code&amp;gt;Shot 1004&amp;lt;/code&amp;gt;. When the user chooses that preset, the actual value of the context variable will be &amp;lt;code&amp;gt;shot1004&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The second method sets all of the preset names and all of the values in one step each. This can be done by setting the &amp;lt;code&amp;gt;presetNames&amp;lt;/code&amp;gt; metadata entry to a Cortex string vector (&amp;lt;code&amp;gt;IECore.StringVectorData&amp;lt;/code&amp;gt;)holding all of the preset names. Setting &amp;lt;code&amp;gt;presetValues&amp;lt;/code&amp;gt; to a Cortex vector of some type, such as &amp;lt;code&amp;gt;IECoreStringVectorData&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;IECoreFloatVectorData&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; UI is built once and then reused for subsequent showings. This means after adding presets, you need to force Gaffer to refresh the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog. The last four lines of the following script show how to do that.&lt;br /&gt;
&lt;br /&gt;
The following script is an example of all of the above steps condensed into a reusable function for adding presets for a global context variable.&amp;lt;pre&amp;gt;&lt;br /&gt;
#test&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Adding_Presets_to_Global_Context_Variables&amp;diff=356</id>
		<title>Adding Presets to Global Context Variables</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Adding_Presets_to_Global_Context_Variables&amp;diff=356"/>
		<updated>2024-07-16T21:34:07Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: Created page with &amp;quot;Global context variables can be useful for ensuring a context variable is always accessible and set for the entire script. Unless it is overridden by a [https://www.gafferhq.org/documentation/1.4.8.0/Reference/NodeReference/Gaffer/ContextVariables.html ContextVariables] or  [https://www.gafferhq.org/documentation/1.4.8.0/Reference/NodeReference/Gaffer/ContextVariableTweaks.html ContextVariablesTweaks] node, all nodes will see the global context variable. There are some g...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Global context variables can be useful for ensuring a context variable is always accessible and set for the entire script. Unless it is overridden by a [https://www.gafferhq.org/documentation/1.4.8.0/Reference/NodeReference/Gaffer/ContextVariables.html ContextVariables] or  [https://www.gafferhq.org/documentation/1.4.8.0/Reference/NodeReference/Gaffer/ContextVariableTweaks.html ContextVariablesTweaks] node, all nodes will see the global context variable. There are some global context variables added by Gaffer by default when creating a new script. You can see these, and add your own, from the &amp;lt;code&amp;gt;Variables&amp;lt;/code&amp;gt; tab in the &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt; dialog accessed from the &amp;lt;code&amp;gt;File.Settings&amp;lt;/code&amp;gt;menu item.&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Main_Page&amp;diff=350</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Main_Page&amp;diff=350"/>
		<updated>2024-07-05T14:12:15Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: Added guide for global context variable presets&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Gaffer Wiki}} &lt;br /&gt;
=Welcome to Gaffer Wiki=&lt;br /&gt;
&lt;br /&gt;
Gaffer Wiki is a community effort and everyone is welcome to contribute. Here you can find [[:Category:Examples|Examples]], Templates, Guides and more for [https://www.gafferhq.org Gaffer]. See [[Help:Getting started|Getting started]] if this is your first time contributing.&lt;br /&gt;
&lt;br /&gt;
== Getting Started With Gaffer ==&lt;br /&gt;
&lt;br /&gt;
If you&#039;re completely new to Gaffer, begin with [[Getting started with Gaffer]].&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
[[:Category:Examples|Examples]] provide small snippets of functionality to demonstrate how to do useful things with Gaffer&#039;s [[:Category:Nodes|Nodes]].&lt;br /&gt;
&lt;br /&gt;
== Templates ==&lt;br /&gt;
&lt;br /&gt;
Templates are more complete scripts, useful as a jumping off point for creating your own Gaffer setups.&lt;br /&gt;
&lt;br /&gt;
== Guides ==&lt;br /&gt;
&lt;br /&gt;
Guides go more in depth into specific aspects of Gaffer. From usage through to customising and extending Gaffer.&lt;br /&gt;
&lt;br /&gt;
* [[Shortcuts and UI Interactions]]&lt;br /&gt;
* [[Installing Gaffer on AWS with EC2 Image Builder]]&lt;br /&gt;
* [[Adding Presets to Global Context Variables]]&lt;br /&gt;
&lt;br /&gt;
== External Resources ==&lt;br /&gt;
&lt;br /&gt;
[https://www.gafferhq.org/documentation Gaffer&#039;s Documentation]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/gafferHQ/gaffer Gaffer GitHub]&lt;br /&gt;
&lt;br /&gt;
[https://www.gafferhq.org/resources GafferHQ Resources]&lt;br /&gt;
&lt;br /&gt;
[https://groups.google.com/g/gaffer-dev Gaffer-Dev Mailing List]&lt;br /&gt;
&lt;br /&gt;
[https://discord.gg/sEm8dDw Gaffer Users Discord]&lt;br /&gt;
&lt;br /&gt;
__NOTOC__&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=313</id>
		<title>Installing Gaffer on AWS with EC2 Image Builder</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=313"/>
		<updated>2024-06-20T21:24:58Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a guide to setting up Amazon Web Services EC2 Image Builder with Gaffer. The EC2 Image Builder is a service from AWS that allows you to create an &#039;&#039;&#039;AMI&#039;&#039;&#039; (Amazon Machine Image) for use with EC2 with all the software and configuration needed to run jobs on AWS. An &#039;&#039;&#039;EC2 instance&#039;&#039;&#039; is a preset configuration of processor, memory and network resources made available by AWS - the virtual equivalent of hardware. An EC2 instance needs to be launched with an AMI that defines the virtual machine that will be running - the operating system and installed software.&lt;br /&gt;
&lt;br /&gt;
This guide is intended for users with some AWS knowledge but not expert level. After completing this guide, you will have a Linux-based EC2 AMI available to your AWS users that can be run on any EC2 instance type for running Gaffer tasks, optionally including Arnold rendering. These instances can be launched manually through the AWS management console, via Python scripts or the AWS terminal, or from applications like Thinkbox&#039;s Deadline.&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
The EC2 Image Builder is split into a number of different parts. We need to work with three of those to create our Gaffer image. [https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html &#039;&#039;&#039;Image Pipelines&#039;&#039;&#039;] are run to create the AMI. With Image Pipelines, you determine the schedule with which it will be run (likely Manual for our purposes) and the Image Recipe that will be used to create the AMI.&lt;br /&gt;
&lt;br /&gt;
An &#039;&#039;&#039;[https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-recipes.html Image Recipe]&#039;&#039;&#039; consists the the base image AMI that will be the starting point for the new AMI, optional additional storage to attach to the instance and a set of components that define the software to be installed.&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;&#039;[https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-components.html Component]&#039;&#039;&#039; is a YAML script describing the set of steps to be performed to install and configure some logical unit of software.&lt;br /&gt;
&lt;br /&gt;
Image Recipes and Components are both versioned. When you save, that version becomes immutable and you will create a new version when making changes or fixes.&lt;br /&gt;
&lt;br /&gt;
This guide will show you how to create Components that can be used to install any version of Gaffer and Arnold through the use of Component parameters. This means you can only have one version of Gaffer and Arnold installed on your AMI. Alternatively, you could create a new Component for each version of Gaffer / Arnold then choose multiple components to install on the same AMI.&lt;br /&gt;
&lt;br /&gt;
=== Getting Started ===&lt;br /&gt;
To start, log into the AWS Console. Pay attention to the region you have set - this setting is in the top-right of the console. The EC2 Image Builder components as well as the generated AMIs (and therefore the EC2 instances you launch with them) are unique per-region.&lt;br /&gt;
&lt;br /&gt;
Choose EC2 Image Builder from the Services menu in the top-left. You can navigate between Image Pipelines, Image Recipes and Components from the left-side menu.&lt;br /&gt;
&lt;br /&gt;
=== Gaffer Component ===&lt;br /&gt;
From the navigation menu, choose Components to see a list of your customized components, which is empty if this is your first time using it.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create component&amp;quot;.&lt;br /&gt;
# Keep &amp;quot;Component type&amp;quot; set to &amp;lt;code&amp;gt;Build&amp;lt;/code&amp;gt;&lt;br /&gt;
# Set the Component Details&lt;br /&gt;
## Choose &amp;lt;code&amp;gt;Linux&amp;lt;/code&amp;gt; as the &amp;quot;Image operating system&amp;quot;. This indicates this recipe is compatible with Linux-based Image Pipelines. You determine the operating system for your AMI in the Image Recipe configuration.&lt;br /&gt;
## From &amp;quot;Compatible OS Versions&amp;quot;, choose the Linux versions you intend for this recipe to be compatible with.&lt;br /&gt;
## Enter a Component name and optionally a description.&lt;br /&gt;
## Enter a Component version, such as &amp;lt;code&amp;gt;1.0.0&amp;lt;/code&amp;gt;&lt;br /&gt;
# Set the Content. This is the YAML script that will be run to install Gaffer. The YAML script below will setup Gaffer.&lt;br /&gt;
# Finally, choose &amp;quot;Save Component&amp;quot; at the bottom of the screen to save it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name: Gaffer Component&lt;br /&gt;
description: Installs software needed for running Gaffer on AWS.&lt;br /&gt;
schemaVersion: 1.0&lt;br /&gt;
&lt;br /&gt;
parameters:&lt;br /&gt;
  - gafferVersion:&lt;br /&gt;
      type: string&lt;br /&gt;
      default: &#039;1.4.7.0&#039;&lt;br /&gt;
      description: &#039;The Gaffer version to install.&#039;&lt;br /&gt;
  - gccVersion:&lt;br /&gt;
      type: string&lt;br /&gt;
      default: &#039;9&#039;&lt;br /&gt;
      description: &#039;The gcc version to target for the Gaffer install.&#039;&lt;br /&gt;
&lt;br /&gt;
phases:&lt;br /&gt;
  - name: build&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: DownloadGaffer&lt;br /&gt;
        action: WebDownload&lt;br /&gt;
        inputs:&lt;br /&gt;
          - source: https://github.com/GafferHQ/gaffer/releases/download/{{gafferVersion}}/gaffer-{{gafferVersion}}-linux-gcc{{gccVersion}}.tar.gz&lt;br /&gt;
            destination: /opt/gaffer-{{gafferVersion}}/gaffer-{{gafferVersion}}-gcc{{gccVersion}}.tar.gz&lt;br /&gt;
&lt;br /&gt;
      - name: ExtractGaffer&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - tar xvzf {{build.DownloadGaffer.inputs[0].destination}} --strip-components=1 -C /opt/gaffer-{{gafferVersion}}&lt;br /&gt;
            - rm {{build.DownloadGaffer.inputs[0].destination}}&lt;br /&gt;
            - echo &#039;GAFFER_ROOT=/opt/gaffer-{{gafferVersion}}&#039; &amp;gt;&amp;gt; .env&lt;br /&gt;
            - echo &#039;GAFFER_VERSION={{gafferVersion}}&#039; &amp;gt;&amp;gt; .env&lt;br /&gt;
&lt;br /&gt;
  - name: validate&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: ValidateGaffer&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - source .env&lt;br /&gt;
            - $GAFFER_ROOT/bin/gaffer env python -c &amp;quot;print(&#039;Gaffer validated&#039;)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;schemaVersion&amp;lt;/code&amp;gt; and the two items under &amp;lt;code&amp;gt;phases&amp;lt;/code&amp;gt; are required. The &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; list is a helpful way of specifying variables. They can be referenced in multiple places, so they make your Components less error-prone. Their value can also be set from within an Image Recipe which makes for much fewer versions of your Component. Without &amp;lt;code&amp;gt;parameter&amp;lt;/code&amp;gt; lists, you would need to version up your Component with each Gaffer version.&lt;br /&gt;
&lt;br /&gt;
==== Build Phase ====&lt;br /&gt;
The first phase of a component build installs Gaffer. It first downloads Gaffer from the Github release URL. Then it extracts the archive to the &amp;lt;code&amp;gt;/opt&amp;lt;/code&amp;gt; directory. Finally, an environment variable is set for other components to locate Gaffer&#039;s root directory.&lt;br /&gt;
&lt;br /&gt;
The extraction step makes use of another helpful feature in Component scripts - referencing variables from a previous step. The &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{build.DownloadGaffer.inputs[0].destination}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; text indicates that the file path to extract is taken from the &amp;lt;code&amp;gt;DownloadGaffer&amp;lt;/code&amp;gt; step of the &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; phase. This is another way to reduce errors from typos in your script.&lt;br /&gt;
&lt;br /&gt;
Note that starting with Gaffer 1.4, a gcc11 and gcc9 build is available. Which of these archives you use depends on the Linux distribution you use as your base image (see &amp;quot;Choosing a base image below&amp;quot; for more information). If you&#039;re running on Amazon Linux 2, you should use the gcc9 build as the sample above does. If you&#039;re using the newer Amazon Linux 2023, you should use the gcc11 build. &lt;br /&gt;
&lt;br /&gt;
==== Validate Phase ====&lt;br /&gt;
The second phase is for verifying that your installation succeeded. For our purposes, running a short Python script from within Gaffer will prove that the installation succeeded and Gaffer is operable. Implementing this phase helps identify problems before the AMI is created. If any of the validation steps fail, the Image Pipeline will be stopped and an error raised.&lt;br /&gt;
&lt;br /&gt;
=== Arnold Component ===&lt;br /&gt;
Creating the Arnold Component is much like the Gaffer Component, with one significant difference. Arnold&#039;s installer is not available publicly so you will need to upload it to a location that EC2 Image Builder can access. It should be kept private to your organization, which makes AWS S3 a good solution. &#039;&#039;&#039;S3&#039;&#039;&#039; is a storage repository you can manually or programmatically upload to. EC2 Image Builder Components have an action for downloading from S3, which makes it easy to incorporate into Components.&lt;br /&gt;
&lt;br /&gt;
# Upload the Arnold Linux archive to a bucket in your S3 storage and note it&#039;s URL. It will start with &amp;lt;code&amp;gt;s3://&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Choose &amp;quot;Create Component&amp;quot; to start a new Component.&lt;br /&gt;
# Set the Component details as you did with the Gaffer Component.&lt;br /&gt;
# An example Component Content script is below.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name: Arnold Component&lt;br /&gt;
description: Installs Arnold for AWS.&lt;br /&gt;
schemaVersion: 1.0&lt;br /&gt;
&lt;br /&gt;
parameters:&lt;br /&gt;
  - arnoldVersion:&lt;br /&gt;
      type: string&lt;br /&gt;
      default: &#039;7.2.5.3&#039;&lt;br /&gt;
      description: &#039;The Arnold version to install.&#039;&lt;br /&gt;
&lt;br /&gt;
phases:&lt;br /&gt;
  - name: build&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: DownloadArnold&lt;br /&gt;
        action: S3Download&lt;br /&gt;
        inputs:&lt;br /&gt;
          - source: s3://hypotheticalinc-image-sources/Arnold-{{arnoldVersion}}-linux.tgz&lt;br /&gt;
            destination: /opt/arnoldRoot/arnold-{{arnoldVersion}}.tgz&lt;br /&gt;
&lt;br /&gt;
      - name: ExtractArnold&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - mkdir /opt/arnoldRoot/{{arnoldVersion}}&lt;br /&gt;
            - tar xvzf {{build.DownloadArnold.inputs[0].destination}} -C /opt/arnoldRoot/{{arnoldVersion}}&lt;br /&gt;
            - rm {{build.DownloadArnold.inputs[0].destination}}&lt;br /&gt;
            - echo &#039;export ARNOLD_ROOT=/opt/arnoldRoot/{{arnoldVersion}}&#039; &amp;gt;&amp;gt; .env&lt;br /&gt;
&lt;br /&gt;
  - name: validate&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: ValidateGafferArnold&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - source .env&lt;br /&gt;
            - $GAFFER_ROOT/bin/gaffer env python -c &amp;quot;import GafferArnold;GafferArnold.ArnoldLight()&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;The Arnold component is similar to the Gaffer Component. Instead of downloading from a publicly available Github release, we get the Arnold archive from our S3 upload. This method can be used for other private archives you may need to install, such as non-public Gaffer extensions.&lt;br /&gt;
&lt;br /&gt;
The validation phase once again runs a Python script in Gaffer. Here we simply import &amp;lt;code&amp;gt;GafferArnold&amp;lt;/code&amp;gt; and attempt to create an &amp;lt;code&amp;gt;ArnoldLight&amp;lt;/code&amp;gt; to verify it is working.&lt;br /&gt;
&lt;br /&gt;
=== Gaffer Prerequisites Component ===&lt;br /&gt;
Depending on the which Linux distribution you are using as the base image for your Image Pipeline, you may need some additional packages installed to run Gaffer. The Amazon Linux 2 base image, for example, needs &amp;lt;code&amp;gt;mesa-libGL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;mesa-libGLU&amp;lt;/code&amp;gt; to run Gaffer tasks. These can be installed with the following Component.&amp;lt;pre&amp;gt;&lt;br /&gt;
name: Gaffer Prerequisites&lt;br /&gt;
description: Required components to run Gaffer.&lt;br /&gt;
schemaVersion: 1.0&lt;br /&gt;
&lt;br /&gt;
phases:&lt;br /&gt;
  - name: build&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: installPackages&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - yum install -y mesa-libGL mesa-libGLU&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Recipe ===&lt;br /&gt;
With your Components defined, you can now create the Image Recipe for generating your AMI. Choose &amp;quot;Image Recipes&amp;quot;. The Recipe list will be empty if you haven&#039;t created on yet.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create image recipe&amp;quot;.&lt;br /&gt;
# Enter a name for your Recipe and optionally a description.&lt;br /&gt;
# Enter a version number, such as &amp;lt;code&amp;gt;1.0.0&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Select an AMI to use as the base image for the Recipe. See the section below for more information about choosing a base image.&lt;br /&gt;
# Enable your &amp;lt;code&amp;gt;Gaffer&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Arnold&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;GafferPrerequisites&amp;lt;/code&amp;gt; Components you created above. You may need to change the search filter to &amp;lt;code&amp;gt;Owned by me&amp;lt;/code&amp;gt;.&lt;br /&gt;
# As you enable each Component, it will be added to the &amp;quot;Selected Components&amp;quot; section.&lt;br /&gt;
# The Components will be added in the order they are listed. Make sure the &amp;lt;code&amp;gt;GafferPrerequisites&amp;lt;/code&amp;gt; Component is first, followed by &amp;lt;code&amp;gt;Gaffer&amp;lt;/code&amp;gt; and then &amp;lt;code&amp;gt;Arnold&amp;lt;/code&amp;gt;. If they are not in the correct order, validation will fail.&lt;br /&gt;
# You can modify the version number to install in the &amp;quot;Selected Components&amp;quot; section. This is also where you can change the installed versions when making a new version of this Image Recipe for future releases.&lt;br /&gt;
# It is also a good idea to change the &amp;quot;Versioning Options&amp;quot; of your Components to &amp;lt;code&amp;gt;Use latest available component version&amp;lt;/code&amp;gt;. This will ensure the latest component is used without needing to create new Image Recipe versions each time a Component is modified. Using the version variables in your Component allows you to update new software versions without needing to change the Component, only the Recipe.&lt;br /&gt;
# If you need to attach additional storage, you can do that in the &amp;quot;Storage (volumes)&amp;quot; section. This can be useful for storing assets on the instance.&lt;br /&gt;
# Choose &amp;quot;Create Recipe&amp;quot; to complete the Recipe.&lt;br /&gt;
&lt;br /&gt;
==== Choosing a base image ====&lt;br /&gt;
The base image is the AMI that will be used as the starting point for your customized AMI. It is booted first, your components are added to it, and a snapshot is taken to be used as your custom AMI.&lt;br /&gt;
&lt;br /&gt;
The Image Recipe creation wizard allows you to choose a variety of standard Linux distributions, images you&#039;ve subscribed to from the AWS Marketplace, or a manually entered AMI ID.&lt;br /&gt;
&lt;br /&gt;
If you are using Deadline, entering an AMI ID can be helpful for identifying the AMI provided by AWS / Thinkbox that has the needed Deadline components preinstalled. One way of finding this ID is to launch a Deadline worker from the AWS Portal in the Deadline Monitor. There are various options for AMIs with DCC software preinstalled. You can choose the generic Linux worker for a clean base AMI. Once the machine has started, go to your EC2 Instances in the AWS Web Console, locate the running instance and note its AMI ID.&lt;br /&gt;
&lt;br /&gt;
=== Image Pipeline ===&lt;br /&gt;
The final step is to create an Image Pipeline. Choose Image Pipelines from the navigation menu to see the list of Pipelines, which is empty if this is your first time using it.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create Image Pipeline&amp;quot; to get started.&lt;br /&gt;
# Enter a name for the pipeline and optionally a description.&lt;br /&gt;
# Change the schedule option to &amp;quot;Manual&amp;quot; so it will only run when you trigger it.&lt;br /&gt;
# Proceed to the next step, to configure the Recipe.&lt;br /&gt;
# Choose the Recipe you created above.&lt;br /&gt;
# Proceed through the remaining wizard screens, accepting the default values.&lt;br /&gt;
When you are finished, refresh the Image Pipeline list. Select your new Pipeline and choose &amp;quot;Run Pipeline&amp;quot; from the &amp;quot;Actions&amp;quot; menu. Choosing the Pipeline in the list will take you to a list of Pipeline runs, your new submission should be in the &amp;lt;code&amp;gt;Building&amp;lt;/code&amp;gt; status.&lt;br /&gt;
&lt;br /&gt;
Once the image has been built and validated, it will be available in your EC2 AMI list for use!&lt;br /&gt;
&lt;br /&gt;
=== Debugging ===&lt;br /&gt;
If your AMI is not successfully built, you can view the log stream for a detailed description of the steps EC2 Image Builder performed, including the results of your Component validation steps. This can be useful for finding what went wrong and making corrections to your Components.&lt;br /&gt;
&lt;br /&gt;
=== Updating Installed Versions ===&lt;br /&gt;
&lt;br /&gt;
# Select your Image Recipe.&lt;br /&gt;
# Choose &amp;quot;Create new version&amp;quot;.&lt;br /&gt;
# Enter the new version numbers in the Component settings.&lt;br /&gt;
# Either create a new Image Pipeline for your new Image Recipe, or modify the existing Image Pipeline to use it in place.&lt;br /&gt;
&lt;br /&gt;
=== GafferDeadline Component ===&lt;br /&gt;
Though it isn&#039;t necessary for using Gaffer on AWS, if you are using Deadline to queue jobs to AWS, you will also need to have GafferDeadline installed. The following script can be used as a Component for GafferDeadline.&amp;lt;pre&amp;gt;&lt;br /&gt;
name: GafferDeadline Component&lt;br /&gt;
description: Installs GafferDeadline for AWS.&lt;br /&gt;
schemaVersion: 1.0&lt;br /&gt;
&lt;br /&gt;
parameters:&lt;br /&gt;
  - gafferDeadlineVersion:&lt;br /&gt;
      type: string&lt;br /&gt;
      default: &#039;0.58.0.0b2&#039;&lt;br /&gt;
      description: &#039;The GafferDeadline version to install.&#039;&lt;br /&gt;
&lt;br /&gt;
phases:&lt;br /&gt;
  - name: build&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: DownloadGafferDeadline&lt;br /&gt;
        action: WebDownload&lt;br /&gt;
        inputs:&lt;br /&gt;
          - source: https://github.com/hypothetical-inc/GafferDeadline/archive/refs/tags/{{gafferDeadlineVersion}}.tar.gz&lt;br /&gt;
            destination: /opt/GafferDeadline/gafferDeadline{{gafferDeadlineVersion}}.tar.gz&lt;br /&gt;
&lt;br /&gt;
      - name: ExtractGafferDeadline&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - tar -xvzf {{build.DownloadGafferDeadline.inputs[0].destination}} --strip-components=1 -C /opt/GafferDeadline&lt;br /&gt;
            - rm {{build.DownloadGafferDeadline.inputs[0].destination}}&lt;br /&gt;
&lt;br /&gt;
  - name: validate&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: ValidateGafferDeadline&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - source .env&lt;br /&gt;
            - export GAFFER_EXTENSION_PATHS=/opt/GafferDeadline&lt;br /&gt;
            - $GAFFER_ROOT/bin/gaffer env python -c &amp;quot;import GafferDeadline;print(help(GafferDeadline))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=312</id>
		<title>Installing Gaffer on AWS with EC2 Image Builder</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=312"/>
		<updated>2024-06-20T20:56:40Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a guide to setting up Amazon Web Services EC2 Image Builder with Gaffer. The EC2 Image Builder is a service from AWS that allows you to create an &#039;&#039;&#039;AMI&#039;&#039;&#039; (Amazon Machine Image) for use with EC2 with all the software and configuration needed to run jobs on AWS. An &#039;&#039;&#039;EC2 instance&#039;&#039;&#039; is a preset configuration of processor, memory and network resources made available by AWS - the virtual equivalent of hardware. An EC2 instance needs to be launched with an AMI that defines the virtual machine that will be running - the operating system and installed software.&lt;br /&gt;
&lt;br /&gt;
This guide is intended for users with some AWS knowledge but not expert level. After completing this guide, you will have a Linux-based EC2 AMI available to your AWS users that can be run on any EC2 instance type for running Gaffer tasks, optionally including Arnold rendering. These instances can be launched manually through the AWS management console, via Python scripts or the AWS terminal, or from applications like Thinkbox&#039;s Deadline.&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
The EC2 Image Builder is split into a number of different parts. We need to work with three of those to create our Gaffer image. [https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html &#039;&#039;&#039;Image Pipelines&#039;&#039;&#039;] are run to create the AMI. With Image Pipelines, you determine the schedule with which it will be run (likely Manual for our purposes) and the Image Recipe that will be used to create the AMI.&lt;br /&gt;
&lt;br /&gt;
An &#039;&#039;&#039;[https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-recipes.html Image Recipe]&#039;&#039;&#039; consists the the base image AMI that will be the starting point for the new AMI, optional additional storage to attach to the instance and a set of components that define the software to be installed.&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;&#039;[https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-components.html Component]&#039;&#039;&#039; is a YAML script describing the set of steps to be performed to install and configure some logical unit of software.&lt;br /&gt;
&lt;br /&gt;
Image Recipes and Components are both versioned. When you save, that version becomes immutable and you will create a new version when making changes or fixes.&lt;br /&gt;
&lt;br /&gt;
This guide will show you how to create Components that can be used to install any version of Gaffer and Arnold through the use of Component parameters. This means you can only have one version of Gaffer and Arnold installed on your AMI. Alternatively, you could create a new Component for each version of Gaffer / Arnold then choose multiple components to install on the same AMI.&lt;br /&gt;
&lt;br /&gt;
=== Getting Started ===&lt;br /&gt;
To start, log into the AWS Console. Pay attention to the region you have set - this setting is in the top-right of the console. The EC2 Image Builder components as well as the generated AMIs (and therefore the EC2 instances you launch with them) are unique per-region.&lt;br /&gt;
&lt;br /&gt;
Choose EC2 Image Builder from the Services menu in the top-left. You can navigate between Image Pipelines, Image Recipes and Components from the left-side menu.&lt;br /&gt;
&lt;br /&gt;
=== Gaffer Component ===&lt;br /&gt;
From the navigation menu, choose Components to see a list of your customized components, which is empty if this is your first time using it.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create component&amp;quot;.&lt;br /&gt;
# Keep &amp;quot;Component type&amp;quot; set to &amp;lt;code&amp;gt;Build&amp;lt;/code&amp;gt;&lt;br /&gt;
# Set the Component Details&lt;br /&gt;
## Choose &amp;lt;code&amp;gt;Linux&amp;lt;/code&amp;gt; as the &amp;quot;Image operating system&amp;quot;. This indicates this recipe is compatible with Linux-based Image Pipelines. You determine the operating system for your AMI in the Image Recipe configuration.&lt;br /&gt;
## From &amp;quot;Compatible OS Versions&amp;quot;, choose the Linux versions you intend for this recipe to be compatible with.&lt;br /&gt;
## Enter a Component name and optionally a description.&lt;br /&gt;
## Enter a Component version, such as &amp;lt;code&amp;gt;1.0.0&amp;lt;/code&amp;gt;&lt;br /&gt;
# Set the Content. This is the YAML script that will be run to install Gaffer. The YAML script below will setup Gaffer.&lt;br /&gt;
# Finally, choose &amp;quot;Save Component&amp;quot; at the bottom of the screen to save it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name: Gaffer Component&lt;br /&gt;
description: Installs Gaffer for running on AWS.&lt;br /&gt;
schemaVersion: 1.0&lt;br /&gt;
&lt;br /&gt;
parameters:&lt;br /&gt;
  - gafferVersion:&lt;br /&gt;
      type: string&lt;br /&gt;
      default: &#039;1.3.7.0&#039;&lt;br /&gt;
      description: &#039;The Gaffer version to install.&#039;&lt;br /&gt;
&lt;br /&gt;
phases:&lt;br /&gt;
  - name: build&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: DownloadGaffer&lt;br /&gt;
        action: WebDownload&lt;br /&gt;
        inputs:&lt;br /&gt;
          - source: https://github.com/GafferHQ/gaffer/releases/download/{{gafferVersion}}/gaffer-{{gafferVersion}}-linux.tar.gz&lt;br /&gt;
            destination: /opt/gaffer-{{gafferVersion}}/gaffer-{{gafferVersion}}.tar.gz&lt;br /&gt;
&lt;br /&gt;
      - name: ExtractGaffer&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - tar xvzf {{build.DownloadGaffer.inputs[0].destination}} --strip-components=1 -C /opt/gaffer-{{gafferVersion}}&lt;br /&gt;
            - rm {{build.DownloadGaffer.inputs[0].destination}}&lt;br /&gt;
            - echo &#039;export GAFFER_ROOT=/opt/gaffer-{{gafferVersion}}&#039; &amp;gt;&amp;gt; /etc/profile&lt;br /&gt;
&lt;br /&gt;
  - name: validate&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: ValidateGaffer&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - $GAFFER_ROOT/bin/gaffer env python -c &amp;quot;print(&#039;Gaffer validated&#039;)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;schemaVersion&amp;lt;/code&amp;gt; and the two items under &amp;lt;code&amp;gt;phases&amp;lt;/code&amp;gt; are required. The &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; list is a helpful way of specifying variables. They can be referenced in multiple places, so they make your Components less error-prone. Their value can also be set from within an Image Recipe which makes for much fewer versions of your Component. Without &amp;lt;code&amp;gt;parameter&amp;lt;/code&amp;gt; lists, you would need to version up your Component with each Gaffer version.&lt;br /&gt;
&lt;br /&gt;
==== Build Phase ====&lt;br /&gt;
The first phase of a component build installs Gaffer. It first downloads Gaffer from the Github release URL. Then it extracts the archive to the &amp;lt;code&amp;gt;/opt&amp;lt;/code&amp;gt; directory. Finally, an environment variable is set for other components to locate Gaffer&#039;s root directory.&lt;br /&gt;
&lt;br /&gt;
The extraction step makes use of another helpful feature in Component scripts - referencing variables from a previous step. The &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{build.DownloadGaffer.inputs[0].destination}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; text indicates that the file path to extract is taken from the &amp;lt;code&amp;gt;DownloadGaffer&amp;lt;/code&amp;gt; step of the &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; phase. This is another way to reduce errors from typos in your script.&lt;br /&gt;
&lt;br /&gt;
Note that starting with Gaffer 1.4, a gcc11 and gcc9 build is available. Which of these archives you use depends on the Linux distribution you use as your base image (see &amp;quot;Choosing a base image below&amp;quot; for more information). If you&#039;re running on Amazon Linux 2, you should use the gcc9 build as the sample above does. If you&#039;re using the newer Amazon Linux 2023, you should use the gcc11 build. &lt;br /&gt;
&lt;br /&gt;
==== Validate Phase ====&lt;br /&gt;
The second phase is for verifying that your installation succeeded. For our purposes, running a short Python script from within Gaffer will prove that the installation succeeded and Gaffer is operable. Implementing this phase helps identify problems before the AMI is created. If any of the validation steps fail, the Image Pipeline will be stopped and an error raised.&lt;br /&gt;
&lt;br /&gt;
=== Arnold Component ===&lt;br /&gt;
Creating the Arnold Component is much like the Gaffer Component, with one significant difference. Arnold&#039;s installer is not available publicly so you will need to upload it to a location that EC2 Image Builder can access. It should be kept private to your organization, which makes AWS S3 a good solution. &#039;&#039;&#039;S3&#039;&#039;&#039; is a storage repository you can manually or programmatically upload to. EC2 Image Builder Components have an action for downloading from S3, which makes it easy to incorporate into Components.&lt;br /&gt;
&lt;br /&gt;
# Upload the Arnold Linux archive to a bucket in your S3 storage and note it&#039;s URL. It will start with &amp;lt;code&amp;gt;s3://&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Choose &amp;quot;Create Component&amp;quot; to start a new Component.&lt;br /&gt;
# Set the Component details as you did with the Gaffer Component.&lt;br /&gt;
# An example Component Content script is below.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name: Arnold Component&lt;br /&gt;
description: Installs Arnold and sets the ARNOLD_ROOT environment variable.&lt;br /&gt;
schemaVersion: 1.0&lt;br /&gt;
&lt;br /&gt;
parameters:&lt;br /&gt;
  - arnoldVersion:&lt;br /&gt;
      type: string&lt;br /&gt;
      default: &#039;7.2.5.3&#039;&lt;br /&gt;
      description: &#039;The Arnold version to install.&#039;&lt;br /&gt;
&lt;br /&gt;
phases:&lt;br /&gt;
  - name: build&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: DownloadArnold&lt;br /&gt;
        action: S3Download&lt;br /&gt;
        inputs:&lt;br /&gt;
          - source: s3://&amp;lt;YOUR BUCKET NAME&amp;gt;/Arnold-{{arnoldVersion}}-linux.tgz&lt;br /&gt;
            destination: /opt/arnoldRoot/arnold-{{arnoldVersion}}.tgz&lt;br /&gt;
&lt;br /&gt;
      - name: ExtractArnold&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - mkdir /opt/arnoldRoot/{{arnoldVersion}}&lt;br /&gt;
            - tar xvzf {{build.DownloadArnold.inputs[0].destination}} -C /opt/arnoldRoot/{{arnoldVersion}}&lt;br /&gt;
            - rm {{build.DownloadArnold.inputs[0].destination}}&lt;br /&gt;
            - echo &#039;export ARNOLD_ROOT=/opt/arnoldRoot/{{arnoldVersion}}&#039; &amp;gt;&amp;gt; /etc/profile&lt;br /&gt;
&lt;br /&gt;
  - name: validate&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: ValidateGafferArnold&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - $GAFFER_ROOT/bin/gaffer env python -c &amp;quot;import GafferArnold;print(help(GafferArnold))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;The Arnold component is similar to the Gaffer Component. Instead of downloading from a publicly available Github release, we get the Arnold archive from our S3 upload. This method can be used for other private archives you may need to install, such as non-public Gaffer extensions.&lt;br /&gt;
&lt;br /&gt;
The validation phase once again runs a Python script in Gaffer. Here we simply import &amp;lt;code&amp;gt;GafferArnold&amp;lt;/code&amp;gt; and attempt to create an &amp;lt;code&amp;gt;ArnoldLight&amp;lt;/code&amp;gt; to verify it is working.&lt;br /&gt;
&lt;br /&gt;
=== Gaffer Prerequisites Component ===&lt;br /&gt;
Depending on the which Linux distribution you are using as the base image for your Image Pipeline, you may need some additional packages installed to run Gaffer. The Amazon Linux 2 base image, for example, needs &amp;lt;code&amp;gt;mesa-libGL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;mesa-libGLU&amp;lt;/code&amp;gt; to run Gaffer tasks. These can be installed with the following Component.&amp;lt;pre&amp;gt;&lt;br /&gt;
name: Gaffer Prerequisites&lt;br /&gt;
description: Required components to run Gaffer.&lt;br /&gt;
schemaVersion: 1.0&lt;br /&gt;
&lt;br /&gt;
phases:&lt;br /&gt;
  - name: build&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: installPackages&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - yum install -y mesa-libGL mesa-libGLU&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Recipe ===&lt;br /&gt;
With your Components defined, you can now create the Image Recipe for generating your AMI. Choose &amp;quot;Image Recipes&amp;quot;. The Recipe list will be empty if you haven&#039;t created on yet.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create image recipe&amp;quot;.&lt;br /&gt;
# Enter a name for your Recipe and optionally a description.&lt;br /&gt;
# Enter a version number, such as &amp;lt;code&amp;gt;1.0.0&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Select an AMI to use as the base image for the Recipe. See the section below for more information about choosing a base image.&lt;br /&gt;
# Enable your &amp;lt;code&amp;gt;Gaffer&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Arnold&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;GafferPrerequisites&amp;lt;/code&amp;gt; Components you created above. You may need to change the search filter to &amp;lt;code&amp;gt;Owned by me&amp;lt;/code&amp;gt;.&lt;br /&gt;
# As you enable each Component, it will be added to the &amp;quot;Selected Components&amp;quot; section.&lt;br /&gt;
# The Components will be added in the order they are listed. Make sure the &amp;lt;code&amp;gt;GafferPrerequisites&amp;lt;/code&amp;gt; Component is first, followed by &amp;lt;code&amp;gt;Gaffer&amp;lt;/code&amp;gt; and then &amp;lt;code&amp;gt;Arnold&amp;lt;/code&amp;gt;. If they are not in the correct order, validation will fail.&lt;br /&gt;
# You can modify the version number to install in the &amp;quot;Selected Components&amp;quot; section. This is also where you can change the installed versions when making a new version of this Image Recipe for future releases.&lt;br /&gt;
# It is also a good idea to change the &amp;quot;Versioning Options&amp;quot; of your Components to &amp;lt;code&amp;gt;Use latest available component version&amp;lt;/code&amp;gt;. This will ensure the latest component is used without needing to create new Image Recipe versions each time a Component is modified. Using the version variables in your Component allows you to update new software versions without needing to change the Component, only the Recipe.&lt;br /&gt;
# If you need to attach additional storage, you can do that in the &amp;quot;Storage (volumes)&amp;quot; section. This can be useful for storing assets on the instance.&lt;br /&gt;
# Choose &amp;quot;Create Recipe&amp;quot; to complete the Recipe.&lt;br /&gt;
&lt;br /&gt;
==== Choosing a base image ====&lt;br /&gt;
The base image is the AMI that will be used as the starting point for your customized AMI. It is booted first, your components are added to it, and a snapshot is taken to be used as your custom AMI.&lt;br /&gt;
&lt;br /&gt;
The Image Recipe creation wizard allows you to choose a variety of standard Linux distributions, images you&#039;ve subscribed to from the AWS Marketplace, or a manually entered AMI ID.&lt;br /&gt;
&lt;br /&gt;
If you are using Deadline, entering an AMI ID can be helpful for identifying the AMI provided by AWS / Thinkbox that has the needed Deadline components preinstalled. One way of finding this ID is to launch a Deadline worker from the AWS Portal in the Deadline Monitor. There are various options for AMIs with DCC software preinstalled. You can choose the generic Linux worker for a clean base AMI. Once the machine has started, go to your EC2 Instances in the AWS Web Console, locate the running instance and note its AMI ID.&lt;br /&gt;
&lt;br /&gt;
=== Image Pipeline ===&lt;br /&gt;
The final step is to create an Image Pipeline. Choose Image Pipelines from the navigation menu to see the list of Pipelines, which is empty if this is your first time using it.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create Image Pipeline&amp;quot; to get started.&lt;br /&gt;
# Enter a name for the pipeline and optionally a description.&lt;br /&gt;
# Change the schedule option to &amp;quot;Manual&amp;quot; so it will only run when you trigger it.&lt;br /&gt;
# Proceed to the next step, to configure the Recipe.&lt;br /&gt;
# Choose the Recipe you created above.&lt;br /&gt;
# Proceed through the remaining wizard screens, accepting the default values.&lt;br /&gt;
When you are finished, refresh the Image Pipeline list. Select your new Pipeline and choose &amp;quot;Run Pipeline&amp;quot; from the &amp;quot;Actions&amp;quot; menu. Choosing the Pipeline in the list will take you to a list of Pipeline runs, your new submission should be in the &amp;lt;code&amp;gt;Building&amp;lt;/code&amp;gt; status.&lt;br /&gt;
&lt;br /&gt;
Once the image has been built and validated, it will be available in your EC2 AMI list for use!&lt;br /&gt;
&lt;br /&gt;
=== Debugging ===&lt;br /&gt;
If your AMI is not successfully built, you can view the log stream for a detailed description of the steps EC2 Image Builder performed, including the results of your Component validation steps. This can be useful for finding what went wrong and making corrections to your Components.&lt;br /&gt;
&lt;br /&gt;
=== Updating Installed Versions ===&lt;br /&gt;
&lt;br /&gt;
# Select your Image Recipe.&lt;br /&gt;
# Choose &amp;quot;Create new version&amp;quot;.&lt;br /&gt;
# Enter the new version numbers in the Component settings.&lt;br /&gt;
# Either create a new Image Pipeline for your new Image Recipe, or modify the existing Image Pipeline to use it in place.&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=311</id>
		<title>Installing Gaffer on AWS with EC2 Image Builder</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=311"/>
		<updated>2024-06-20T15:40:08Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a guide to setting up Amazon Web Services EC2 Image Builder with Gaffer. The EC2 Image Builder is a service from AWS that allows you to create an &#039;&#039;&#039;AMI&#039;&#039;&#039; (Amazon Machine Image) for use with EC2 with all the software and configuration needed to run jobs on AWS. An &#039;&#039;&#039;EC2 instance&#039;&#039;&#039; is a preset configuration of processor, memory and network resources made available by AWS - the virtual equivalent of hardware. An EC2 instance needs to be launched with an AMI that defines the virtual machine that will be running - the operating system and installed software.&lt;br /&gt;
&lt;br /&gt;
This guide is intended for users with some AWS knowledge but not expert level. After completing this guide, you will have a Linux-based EC2 AMI available to your AWS users that can be run on any EC2 instance type for running Gaffer tasks, including Arnold rendering. These instances can be launched manually through the AWS management console, via Python scripts or the AWS terminal, or from applications like Thinkbox&#039;s Deadline.&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
The EC2 Image Builder is split into a number of different parts. We need to work with three of those to create our Gaffer image. [https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html &#039;&#039;&#039;Image Pipelines&#039;&#039;&#039;] are run to create the AMI. With Image Pipelines, you determine the schedule with which it will be run (likely Manual for our purposes) and the Image Recipe that will be used to create the AMI.&lt;br /&gt;
&lt;br /&gt;
An &#039;&#039;&#039;[https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-recipes.html Image Recipe]&#039;&#039;&#039; consists the the base image AMI that will be the starting point for the new AMI, optional additional storage to attach to the instance and a set of components that define the software to be installed.&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;&#039;[https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-components.html Component]&#039;&#039;&#039; is a YAML script describing the set of steps to be performed to install and configure some logical unit of software.&lt;br /&gt;
&lt;br /&gt;
Image Recipes and Components are both versioned. When you save, that version becomes immutable and you will create a new version when making changes or fixes.&lt;br /&gt;
&lt;br /&gt;
=== Getting Started ===&lt;br /&gt;
To start, log into the AWS Console. Pay attention to the region you have set - this setting is in the top-right of the console. The EC2 Image Builder components as well as the generated AMIs (and therefore the EC2 instances you launch with them) are unique per-region.&lt;br /&gt;
&lt;br /&gt;
Choose EC2 Image Builder from the Services menu in the top-left. You can navigate between Image Pipelines, Image Recipes and Components from the left-side menu.&lt;br /&gt;
&lt;br /&gt;
=== Gaffer Component ===&lt;br /&gt;
From the navigation menu, choose Components to see a list of your customized components, which is empty if this is your first time using it.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create component&amp;quot;.&lt;br /&gt;
# Keep &amp;quot;Component type&amp;quot; set to &amp;lt;code&amp;gt;Build&amp;lt;/code&amp;gt;&lt;br /&gt;
# Set the Component Details&lt;br /&gt;
## Choose &amp;lt;code&amp;gt;Linux&amp;lt;/code&amp;gt; as the &amp;quot;Image operating system&amp;quot;. This indicates this recipe is compatible with Linux-based Image Pipelines. You determine the operating system for your AMI in the Image Pipeline configuration.&lt;br /&gt;
## From &amp;quot;Compatible OS Versions&amp;quot;, choose the Linux versions you intend for this recipe to be compatible with.&lt;br /&gt;
## Enter a Component name and optionally a description.&lt;br /&gt;
## Enter a Component version, such as &amp;lt;code&amp;gt;1.0.0&amp;lt;/code&amp;gt;&lt;br /&gt;
# Set the Content. This is the YAML script that will be run to install Gaffer. The YAML script below will setup Gaffer.&lt;br /&gt;
# Finally, choose &amp;quot;Save Component&amp;quot; at the bottom of the screen to save it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name: Gaffer Component&lt;br /&gt;
description: Installs Gaffer for running on AWS.&lt;br /&gt;
schemaVersion: 1.0&lt;br /&gt;
&lt;br /&gt;
parameters:&lt;br /&gt;
  - gafferVersion:&lt;br /&gt;
      type: string&lt;br /&gt;
      default: &#039;1.3.7.0&#039;&lt;br /&gt;
      description: &#039;The Gaffer version to install.&#039;&lt;br /&gt;
&lt;br /&gt;
phases:&lt;br /&gt;
  - name: build&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: DownloadGaffer&lt;br /&gt;
        action: WebDownload&lt;br /&gt;
        inputs:&lt;br /&gt;
          - source: https://github.com/GafferHQ/gaffer/releases/download/{{gafferVersion}}/gaffer-{{gafferVersion}}-linux.tar.gz&lt;br /&gt;
            destination: /opt/gaffer-{{gafferVersion}}/gaffer-{{gafferVersion}}.tar.gz&lt;br /&gt;
&lt;br /&gt;
      - name: ExtractGaffer&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - tar xvzf {{build.DownloadGaffer.inputs[0].destination}} --strip-components=1 -C /opt/gaffer-{{gafferVersion}}&lt;br /&gt;
            - rm {{build.DownloadGaffer.inputs[0].destination}}&lt;br /&gt;
            - echo &#039;export GAFFER_ROOT=/opt/gaffer-{{gafferVersion}}&#039; &amp;gt;&amp;gt; /etc/profile&lt;br /&gt;
&lt;br /&gt;
  - name: validate&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: ValidateGaffer&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - $GAFFER_ROOT/bin/gaffer env python -c &amp;quot;print(&#039;Gaffer validated&#039;)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;schemaVersion&amp;lt;/code&amp;gt; and the two items under &amp;lt;code&amp;gt;phases&amp;lt;/code&amp;gt; are required. The &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; list is a helpful way of specifying variables. They can be referenced in multiple places, so they make your Components less error-prone. Their value can also be set from within an Image Recipe which makes for much fewer versions of your Component. Without &amp;lt;code&amp;gt;parameter&amp;lt;/code&amp;gt; lists, you would need to version up your Component with each Gaffer version.&lt;br /&gt;
&lt;br /&gt;
==== Build Phase ====&lt;br /&gt;
The first phase of a component build installs Gaffer. It first downloads Gaffer from the Github release URL. Then it extracts the archive to the &amp;lt;code&amp;gt;/opt&amp;lt;/code&amp;gt; directory. Finally, an environment variable is set for other components to locate Gaffer&#039;s root directory.&lt;br /&gt;
&lt;br /&gt;
The extraction step makes use of another helpful feature in Component scripts - referencing variables from a previous step. The &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{build.DownloadGaffer.inputs[0].destination}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; text indicates that the file path to extract is taken from the &amp;lt;code&amp;gt;DownloadGaffer&amp;lt;/code&amp;gt; step of the &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; phase. This is another way to reduce errors from typos in your script.&lt;br /&gt;
&lt;br /&gt;
==== Validate Phase ====&lt;br /&gt;
The second phase is for verifying that your installation succeeded. For our purposes, running a short Python script from within Gaffer will prove that the installation succeeded and Gaffer is operable. Implementing this phase helps identify problems before the AMI is created. If any of the validation steps fail, the Image Pipeline will be stopped and an error raised.&lt;br /&gt;
&lt;br /&gt;
=== Arnold Component ===&lt;br /&gt;
Creating the Arnold Component is much like the Gaffer Component, with one significant difference. Arnold&#039;s installer is not available publicly so you will need to upload it to a location that EC2 Image Builder can access. It should be kept private to your organization, which makes AWS S3 a good solution. &#039;&#039;&#039;S3&#039;&#039;&#039; is a storage repository you can manually or programmatically upload to. EC2 Image Builder Components have an action for downloading from S3, which makes it easy to incorporate into Components.&lt;br /&gt;
&lt;br /&gt;
# Upload the Arnold Linux archive to a bucket in your S3 storage and note it&#039;s URL. It will start with &amp;lt;code&amp;gt;s3://&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Choose &amp;quot;Create Component&amp;quot; to start a new Component.&lt;br /&gt;
# Set the Component details as you did with the Gaffer Component.&lt;br /&gt;
# An example Component Content script is below.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name: Arnold Component&lt;br /&gt;
description: Installs Arnold and sets the ARNOLD_ROOT environment variable.&lt;br /&gt;
schemaVersion: 1.0&lt;br /&gt;
&lt;br /&gt;
parameters:&lt;br /&gt;
  - arnoldVersion:&lt;br /&gt;
      type: string&lt;br /&gt;
      default: &#039;7.2.5.3&#039;&lt;br /&gt;
      description: &#039;The Arnold version to install.&#039;&lt;br /&gt;
&lt;br /&gt;
phases:&lt;br /&gt;
  - name: build&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: DownloadArnold&lt;br /&gt;
        action: S3Download&lt;br /&gt;
        inputs:&lt;br /&gt;
          - source: s3://&amp;lt;YOUR BUCKET NAME&amp;gt;/Arnold-{{arnoldVersion}}-linux.tgz&lt;br /&gt;
            destination: /opt/arnoldRoot/arnold-{{arnoldVersion}}.tgz&lt;br /&gt;
&lt;br /&gt;
      - name: ExtractArnold&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - mkdir /opt/arnoldRoot/{{arnoldVersion}}&lt;br /&gt;
            - tar xvzf {{build.DownloadArnold.inputs[0].destination}} -C /opt/arnoldRoot/{{arnoldVersion}}&lt;br /&gt;
            - rm {{build.DownloadArnold.inputs[0].destination}}&lt;br /&gt;
            - echo &#039;export ARNOLD_ROOT=/opt/arnoldRoot/{{arnoldVersion}}&#039; &amp;gt;&amp;gt; /etc/profile&lt;br /&gt;
&lt;br /&gt;
  - name: validate&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: ValidateGafferArnold&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - $GAFFER_ROOT/bin/gaffer env python -c &amp;quot;import GafferArnold;print(help(GafferArnold))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;The Arnold component is similar to the Gaffer Component. Instead of downloading from a publicly available Github release, we get the Arnold archive from our S3 upload. This method can be used for other private archives you may need to install, such as non-public Gaffer extensions.&lt;br /&gt;
&lt;br /&gt;
The validation phase once again runs a Python script in Gaffer. Here we simply import &amp;lt;code&amp;gt;GafferArnold&amp;lt;/code&amp;gt; and attempt to create an &amp;lt;code&amp;gt;ArnoldLight&amp;lt;/code&amp;gt; to verify it is working.&lt;br /&gt;
&lt;br /&gt;
=== Gaffer Prerequisites Component ===&lt;br /&gt;
Depending on the which Linux distribution you are using as the base image for your Image Pipeline, you may need some additional packages installed to run Gaffer. The Amazon Linux 2 base image, for example, needs &amp;lt;code&amp;gt;mesa-libGL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;mesa-libGLU&amp;lt;/code&amp;gt; to run Gaffer tasks. These can be installed with the following Component.&amp;lt;pre&amp;gt;&lt;br /&gt;
name: Gaffer Prerequisites&lt;br /&gt;
description: Required components to run Gaffer.&lt;br /&gt;
schemaVersion: 1.0&lt;br /&gt;
&lt;br /&gt;
phases:&lt;br /&gt;
  - name: build&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: installPackages&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - yum install -y mesa-libGL mesa-libGLU&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Recipe ===&lt;br /&gt;
With your Components defined, you can now create the Image Recipe for generating your AMI. Choose &amp;quot;Image Recipes&amp;quot;. The Recipe list will be empty if you haven&#039;t created on yet.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create image recipe&amp;quot;.&lt;br /&gt;
# Enter a name for your Recipe and optionally a description.&lt;br /&gt;
# Enter a version number, such as &amp;lt;code&amp;gt;1.0.0&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Select an AMI to use as the base image for the Recipe. See the section below for more information about choosing a base image.&lt;br /&gt;
# Enable your &amp;lt;code&amp;gt;Gaffer&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Arnold&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;GafferPrerequisites&amp;lt;/code&amp;gt; Components you created above. You may need to change the search filter to &amp;lt;code&amp;gt;Owned by me&amp;lt;/code&amp;gt;.&lt;br /&gt;
# As you enable each Component, it will be added to the &amp;quot;Selected Components&amp;quot; section.&lt;br /&gt;
# The Components will be added in the order they are listed. Make sure the &amp;lt;code&amp;gt;GafferPrerequisites&amp;lt;/code&amp;gt; Component is first, followed by &amp;lt;code&amp;gt;Gaffer&amp;lt;/code&amp;gt; and then &amp;lt;code&amp;gt;Arnold&amp;lt;/code&amp;gt;. If they are not in the correct order, validation will fail.&lt;br /&gt;
# You can modify the version number to install in the &amp;quot;Selected Components&amp;quot; section. This is also where you can change the installed versions when making a new version of this Image Recipe for future releases.&lt;br /&gt;
# It is also a good idea to change the &amp;quot;Versioning Options&amp;quot; of your Components to &amp;lt;code&amp;gt;Use latest available component version&amp;lt;/code&amp;gt;. This will ensure the latest component is used without needing to create new Image Recipe versions each time a Component is modified. Using the version variables in your Component allows you to update new software versions without needing to change the Component, only the Recipe.&lt;br /&gt;
# If you need to attach additional storage, you can do that in the &amp;quot;Storage (volumes)&amp;quot; section. This can be useful for storing assets on the instance.&lt;br /&gt;
# Choose &amp;quot;Create Recipe&amp;quot; to complete the Recipe.&lt;br /&gt;
&lt;br /&gt;
==== Choosing a base image ====&lt;br /&gt;
The base image is the AMI that will be used as the starting point for your customized AMI. It is booted first, your components are added to it, and a snapshot is taken to be used as your custom AMI.&lt;br /&gt;
&lt;br /&gt;
The Image Recipe creation wizard allows you to choose a variety of standard Linux distributions, images you&#039;ve subscribed to from the AWS Marketplace, or a manually entered AMI ID.&lt;br /&gt;
&lt;br /&gt;
If you are using Deadline, entering an AMI ID can be helpful for identifying the AMI provided by AWS / Thinkbox that has the needed Deadline components preinstalled. One way of finding this ID is to launch a Deadline worker from the AWS Portal in the Deadline Monitor. There are various options for AMIs with DCC software preinstalled. You can choose the generic Linux worker for a clean base AMI. Once the machine has started, go to your EC2 Instances in the AWS Web Console, locate the running instance and note its AMI ID.&lt;br /&gt;
&lt;br /&gt;
=== Image Pipeline ===&lt;br /&gt;
The final step is to create an Image Pipeline. Choose Image Pipelines from the navigation menu to see the list of Pipelines, which is empty if this is your first time using it.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create Image Pipeline&amp;quot; to get started.&lt;br /&gt;
# Enter a name for the pipeline and optionally a description.&lt;br /&gt;
# Change the schedule option to &amp;quot;Manual&amp;quot; so it will only run when you trigger it.&lt;br /&gt;
# Proceed to the next step, to configure the Recipe.&lt;br /&gt;
# Choose the Recipe you created above.&lt;br /&gt;
# Proceed through the remaining wizard screens, accepting the default values.&lt;br /&gt;
When you are finished, refresh the Image Pipeline list. Select your new Pipeline and choose &amp;quot;Run Pipeline&amp;quot; from the &amp;quot;Actions&amp;quot; menu. Choosing the Pipeline in the list will take you to a list of Pipeline runs, your new submission should be in the &amp;lt;code&amp;gt;Building&amp;lt;/code&amp;gt; status.&lt;br /&gt;
&lt;br /&gt;
Once the image has been built and validated, it will be available in your EC2 AMI list for use!&lt;br /&gt;
&lt;br /&gt;
=== Debugging ===&lt;br /&gt;
If your AMI is not successfully built, you can view the log stream for a detailed description of the steps EC2 Image Builder performed, including the results of your Component validation steps. This can be useful for finding what went wrong and making corrections to your Components.&lt;br /&gt;
&lt;br /&gt;
=== Updating Installed Versions ===&lt;br /&gt;
&lt;br /&gt;
# Select your Image Recipe.&lt;br /&gt;
# Choose &amp;quot;Create new version&amp;quot;.&lt;br /&gt;
# Enter the new version numbers in the Component settings.&lt;br /&gt;
# Either create a new Image Pipeline for your new Image Recipe, or modify the existing Image Pipeline to use it in place.&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=310</id>
		<title>Installing Gaffer on AWS with EC2 Image Builder</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=310"/>
		<updated>2024-06-19T21:36:22Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a guide to setting up Amazon Web Services EC2 Image Builder with Gaffer. The EC2 Image Builder is a service from AWS that allows you to create an &#039;&#039;&#039;AMI&#039;&#039;&#039; (Amazon Machine Image) for use with EC2 with all the software and configuration needed to run jobs on AWS. An &#039;&#039;&#039;EC2 instance&#039;&#039;&#039; is a preset configuration of processor, memory and network resources made available by AWS - the virtual equivalent of hardware. An EC2 instance needs to be launched with an AMI that defines the virtual machine that will be running - the operating system and installed software.&lt;br /&gt;
&lt;br /&gt;
This guide is intended for users with some AWS knowledge but not expert level. After completing this guide, you will have a Linux-based EC2 AMI available to your AWS users that can be run on any EC2 instance type for running Gaffer tasks, including Arnold rendering. These instances can be launched manually through the AWS management console, via Python scripts or the AWS terminal, or from applications like Thinkbox&#039;s Deadline.&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
The EC2 Image Builder is split into a number of different parts. We need to work with three of those to create our Gaffer image. [https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html &#039;&#039;&#039;Image Pipelines&#039;&#039;&#039;] are run to create the AMI. With Image Pipelines, you determine the schedule with which it will be run (likely Manual for our purposes) and the Image Recipe that will be used to create the AMI.&lt;br /&gt;
&lt;br /&gt;
An &#039;&#039;&#039;[https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-recipes.html Image Recipe]&#039;&#039;&#039; consists the the base image AMI that will be the starting point for the new AMI, optional additional storage to attach to the instance and a set of components that define the software to be installed.&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;&#039;[https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-components.html Component]&#039;&#039;&#039; is a YAML script describing the set of steps to be performed to install and configure some logical unit of software.&lt;br /&gt;
&lt;br /&gt;
Image Recipes and Components are both versioned. When you save, that version becomes immutable and you will create a new version when making changes or fixes.&lt;br /&gt;
&lt;br /&gt;
=== Getting Started ===&lt;br /&gt;
To start, log into the AWS Console. Pay attention to the region you have set - this setting is in the top-right of the console. The EC2 Image Builder components as well as the generated AMIs (and therefore the EC2 instances you launch with them) are unique per-region.&lt;br /&gt;
&lt;br /&gt;
Choose EC2 Image Builder from the Services menu in the top-left. You can navigate between Image Pipelines, Image Recipes and Components from the left-side menu.&lt;br /&gt;
&lt;br /&gt;
=== Gaffer Component ===&lt;br /&gt;
From the navigation menu, choose Components to see a list of your customized components, which is empty if this is your first time using it.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create component&amp;quot;.&lt;br /&gt;
# Keep &amp;quot;Component type&amp;quot; set to &amp;lt;code&amp;gt;Build&amp;lt;/code&amp;gt;&lt;br /&gt;
# Set the Component Details&lt;br /&gt;
## Choose &amp;lt;code&amp;gt;Linux&amp;lt;/code&amp;gt; as the &amp;quot;Image operating system&amp;quot;. This indicates this recipe is compatible with Linux-based Image Pipelines. You determine the operating system for your AMI in the Image Pipeline configuration.&lt;br /&gt;
## From &amp;quot;Compatible OS Versions&amp;quot;, choose the Linux versions you intend for this recipe to be compatible with.&lt;br /&gt;
## Enter a Component name.&lt;br /&gt;
## Enter a Component version, such as &amp;lt;code&amp;gt;1.0.0&amp;lt;/code&amp;gt;&lt;br /&gt;
# Set the Content. This is the YAML script that will be run to install Gaffer. The YAML script below will setup Gaffer.&lt;br /&gt;
# Finally, choose &amp;quot;Save Component&amp;quot; at the bottom of the screen to save it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name: Worker Image&lt;br /&gt;
description: Installs software needed for rendering on AWS. This should be loaded into an EC2 Image Builder Configuration for this project.&lt;br /&gt;
schemaVersion: 1.0&lt;br /&gt;
&lt;br /&gt;
parameters:&lt;br /&gt;
  - gafferVersion:&lt;br /&gt;
      type: string&lt;br /&gt;
      default: &#039;1.3.7.0&#039;&lt;br /&gt;
      description: &#039;The Gaffer version to install.&#039;&lt;br /&gt;
&lt;br /&gt;
phases:&lt;br /&gt;
  - name: build&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: DownloadGaffer&lt;br /&gt;
        action: WebDownload&lt;br /&gt;
        inputs:&lt;br /&gt;
          - source: https://github.com/GafferHQ/gaffer/releases/download/{{gafferVersion}}/gaffer-{{gafferVersion}}-linux.tar.gz&lt;br /&gt;
            destination: /opt/gaffer-{{gafferVersion}}/gaffer-{{gafferVersion}}.tar.gz&lt;br /&gt;
&lt;br /&gt;
      - name: ExtractGaffer&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - tar xvzf {{build.DownloadGaffer.inputs[0].destination}} --strip-components=1 -C /opt/gaffer-{{gafferVersion}}&lt;br /&gt;
            - rm {{build.DownloadGaffer.inputs[0].destination}}&lt;br /&gt;
            - echo &#039;export GAFFER_ROOT=/opt/gaffer-{{gafferVersion}}&#039; &amp;gt;&amp;gt; /etc/profile&lt;br /&gt;
&lt;br /&gt;
  - name: validate&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: ValidateGaffer&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - $GAFFER_ROOT/bin/gaffer env python -c &amp;quot;print(&#039;Gaffer validated&#039;)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;schemaVersion&amp;lt;/code&amp;gt; and the two items under &amp;lt;code&amp;gt;phases&amp;lt;/code&amp;gt; are required. The &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; list is a helpful way of specifying variables. They can be referenced in multiple places, so they make your Components less error-prone. Their value can also be set from within an Image Recipe which makes for much fewer versions of your Component. Without &amp;lt;code&amp;gt;parameter&amp;lt;/code&amp;gt; lists, you would need to version up your Component with each Gaffer version.&lt;br /&gt;
&lt;br /&gt;
==== Build Phase ====&lt;br /&gt;
The first phase of a component build installs Gaffer. It first downloads Gaffer from the Github release URL. Then it extracts the archive to the &amp;lt;code&amp;gt;/opt&amp;lt;/code&amp;gt; directory. Finally, an environment variable is set for other components to locate Gaffer&#039;s root directory.&lt;br /&gt;
&lt;br /&gt;
The extraction step makes use of another helpful feature in Component scripts - referencing variables from a previous step. The &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{build.DownloadGaffer.inputs[0].destination}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; text indicates that the file path to extract is taken from the &amp;lt;code&amp;gt;DownloadGaffer&amp;lt;/code&amp;gt; step of the &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; phase. This is another way to reduce errors from typos in your script.&lt;br /&gt;
&lt;br /&gt;
==== Validate Phase ====&lt;br /&gt;
The second phase is for verifying that your installation succeeded. For our purposes, running a short Python script from within Gaffer will prove that the installation succeeded and Gaffer is operable. Implementing this phase helps identify problems before the AMI is created. If any of the validation steps fail, the Image Pipeline will be stopped and an error raised.&lt;br /&gt;
&lt;br /&gt;
=== Arnold Component ===&lt;br /&gt;
Creating the Arnold Component is much like the Gaffer Component, with one significant difference. Arnold&#039;s installer is not available publicly so you will need to upload it to some location that EC2 Image Builder can access. It should be kept private to your organization, which makes AWS S3 a good solution. &#039;&#039;&#039;S3&#039;&#039;&#039; is a storage repository you can manually or programmatically upload to. EC2 Image Builder Components have an action for downloading from S3, which makes it easy to incorporate into Components.&lt;br /&gt;
&lt;br /&gt;
# Upload the Arnold Linux archive to a bucket in your S3 storage and note it&#039;s URL. It will start with &amp;lt;code&amp;gt;s3://&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Choose &amp;quot;Create Component&amp;quot; to start a new Component.&lt;br /&gt;
# Set the Component details as you did with the Gaffer Component.&lt;br /&gt;
# An example Component Content script is below.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name: Arnold Component&lt;br /&gt;
description: Installs Arnold and sets the ARNOLD_ROOT environment variable.&lt;br /&gt;
schemaVersion: 1.0&lt;br /&gt;
&lt;br /&gt;
parameters:&lt;br /&gt;
  - arnoldVersion:&lt;br /&gt;
      type: string&lt;br /&gt;
      default: &#039;7.2.5.3&#039;&lt;br /&gt;
      description: &#039;The Arnold version to install.&#039;&lt;br /&gt;
&lt;br /&gt;
phases:&lt;br /&gt;
  - name: build&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: DownloadArnold&lt;br /&gt;
        action: S3Download&lt;br /&gt;
        inputs:&lt;br /&gt;
          - source: s3://hypotheticalinc-image-sources/Arnold-{{arnoldVersion}}-linux.tgz&lt;br /&gt;
            destination: /opt/arnoldRoot/arnold-{{arnoldVersion}}.tgz&lt;br /&gt;
&lt;br /&gt;
      - name: ExtractArnold&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - mkdir /opt/arnoldRoot/{{arnoldVersion}}&lt;br /&gt;
            - tar xvzf {{build.DownloadArnold.inputs[0].destination}} -C /opt/arnoldRoot/{{arnoldVersion}}&lt;br /&gt;
            - rm {{build.DownloadArnold.inputs[0].destination}}&lt;br /&gt;
            - echo &#039;export ARNOLD_ROOT=/opt/arnoldRoot/{{arnoldVersion}}&#039; &amp;gt;&amp;gt; /etc/profile&lt;br /&gt;
&lt;br /&gt;
  - name: validate&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: ValidateGafferArnold&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - $GAFFER_ROOT/bin/gaffer env python -c &amp;quot;import GafferArnold;print(help(GafferArnold))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;The Arnold component is similar to the Gaffer Component. Instead of downloading from a publicly available Github release, we get the Arnold archive from our S3 upload. This method can be used for other private archives you may need to install, such as non-public Gaffer extensions.&lt;br /&gt;
&lt;br /&gt;
The validation phase once again runs a Python script in Gaffer. Here we simply import &amp;lt;code&amp;gt;GafferArnold&amp;lt;/code&amp;gt; and attempt to create an &amp;lt;code&amp;gt;ArnoldLight&amp;lt;/code&amp;gt; to verify it is working.&lt;br /&gt;
&lt;br /&gt;
=== Gaffer Prerequisites Component ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name: Gaffer Prerequisites&lt;br /&gt;
description: Required components to run Gaffer.&lt;br /&gt;
schemaVersion: 1.0&lt;br /&gt;
&lt;br /&gt;
phases:&lt;br /&gt;
  - name: build&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: installPackages&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - yum install -y mesa-libGL mesa-libGLU&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Recipe ===&lt;br /&gt;
&lt;br /&gt;
=== Image Pipeline ===&lt;br /&gt;
Choose Image Pipelines to see the list of Pipelines, which is empty if this is your first time using it.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create Image Pipeline&amp;quot; to get started.&lt;br /&gt;
# Enter a name for the pipeline and optionally a description.&lt;br /&gt;
# Change the schedule option to &amp;quot;Manual&amp;quot; so it will only run when you trigger it.&lt;br /&gt;
# Proceed to the next step, to configure the Recipe.&lt;br /&gt;
#&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=309</id>
		<title>Installing Gaffer on AWS with EC2 Image Builder</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=309"/>
		<updated>2024-06-19T21:09:46Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a guide to setting up Amazon Web Services EC2 Image Builder with Gaffer. The EC2 Image Builder is a service from AWS that allows you to create an &#039;&#039;&#039;AMI&#039;&#039;&#039; (Amazon Machine Image) for use with EC2 with all the software and configuration needed to run jobs on AWS. An &#039;&#039;&#039;EC2 instance&#039;&#039;&#039; is a preset configuration of processor, memory and network resources made available by AWS - the virtual equivalent of hardware. An EC2 instance needs to be launched with an AMI that defines the virtual machine that will be running - the operating system and installed software.&lt;br /&gt;
&lt;br /&gt;
This guide is intended for users with some AWS knowledge but not expert level. After completing this guide, you will have a Linux-based EC2 AMI available to your AWS users that can be run on any EC2 instance type for running Gaffer tasks, including Arnold rendering. These instances can be launched manually through the AWS management console, via Python scripts or the AWS terminal, or from applications like Thinkbox&#039;s Deadline.&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
The EC2 Image Builder is split into a number of different parts. We need to work with three of those to create our Gaffer image. [https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html &#039;&#039;&#039;Image Pipelines&#039;&#039;&#039;] are run to create the AMI. With Image Pipelines, you determine the schedule with which it will be run (likely Manual for our purposes) and the Image Recipe that will be used to create the AMI.&lt;br /&gt;
&lt;br /&gt;
An &#039;&#039;&#039;[https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-recipes.html Image Recipe]&#039;&#039;&#039; consists the the base image AMI that will be the starting point for the new AMI, optional additional storage to attach to the instance and a set of components that define the software to be installed.&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;&#039;[https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-components.html Component]&#039;&#039;&#039; is a YAML script describing the set of steps to be performed to install and configure some logical unit of software.&lt;br /&gt;
&lt;br /&gt;
Image Recipes and Components are both versioned. When you save, that version becomes immutable and you will create a new version when making changes or fixes.&lt;br /&gt;
&lt;br /&gt;
=== Getting Started ===&lt;br /&gt;
To start, log into the AWS Console. Pay attention to the region you have set - this setting is in the top-right of the console. The EC2 Image Builder components as well as the generated AMIs (and therefore the EC2 instances you launch with them) are unique per-region.&lt;br /&gt;
&lt;br /&gt;
Choose EC2 Image Builder from the Services menu in the top-left. You can navigate between Image Pipelines, Image Recipes and Components from the left-side menu.&lt;br /&gt;
&lt;br /&gt;
=== Gaffer Component ===&lt;br /&gt;
From the navigation menu, choose Components to see a list of your customized components, which is empty if this is your first time using it.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create component&amp;quot;.&lt;br /&gt;
# Keep &amp;quot;Component type&amp;quot; set to &amp;lt;code&amp;gt;Build&amp;lt;/code&amp;gt;&lt;br /&gt;
# Set the Component Details&lt;br /&gt;
## Choose &amp;lt;code&amp;gt;Linux&amp;lt;/code&amp;gt; as the &amp;quot;Image operating system&amp;quot;. This indicates this recipe is compatible with Linux-based Image Pipelines. You determine the operating system for your AMI in the Image Pipeline configuration.&lt;br /&gt;
## From &amp;quot;Compatible OS Versions&amp;quot;, choose the Linux versions you intend for this recipe to be compatible with.&lt;br /&gt;
## Enter a Component name.&lt;br /&gt;
## Enter a Component version, such as &amp;lt;code&amp;gt;1.0.0&amp;lt;/code&amp;gt;&lt;br /&gt;
# Set the Content. This is the YAML script that will be run to install Gaffer. The following YAML script will setup Gaffer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name: Gaffer Component&lt;br /&gt;
description: Installs Gaffer for running on AWS EC2 instances.&lt;br /&gt;
schemaVersion: 1.0&lt;br /&gt;
&lt;br /&gt;
parameters:&lt;br /&gt;
  - gafferVersion:&lt;br /&gt;
      type: string&lt;br /&gt;
      default: &#039;1.3.7.0&#039;&lt;br /&gt;
      description: &#039;The Gaffer version to install.&#039;&lt;br /&gt;
  &lt;br /&gt;
phases:&lt;br /&gt;
  - name: build&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: DownloadGaffer&lt;br /&gt;
        action: WebDownload&lt;br /&gt;
        inputs:&lt;br /&gt;
          - source: https://github.com/GafferHQ/gaffer/releases/download/{{gafferVersion}}/gaffer-{{gafferVersion}}-linux.tar.gz&lt;br /&gt;
            destination: /opt/gaffer-{{gafferVersion}}/gaffer-{{gafferVersion}}.tar.gz&lt;br /&gt;
&lt;br /&gt;
      - name: ExtractGaffer&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - tar xvzf {{build.DownloadGaffer.inputs[0].destination}} --strip-components=1 -C /opt/gaffer-{{gafferVersion}}&lt;br /&gt;
            - rm {{build.DownloadGaffer.inputs[0].destination}}&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;schemaVersion&amp;lt;/code&amp;gt; and the two items under &amp;lt;code&amp;gt;phases&amp;lt;/code&amp;gt; are required. The &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; list is a helpful way of specifying variables. They can be referenced in multiple places, so they make your Components less error-prone. Their value can also be set from within an Image Recipe which makes for much fewer versions of your Component. Without &amp;lt;code&amp;gt;parameter&amp;lt;/code&amp;gt; lists, you would need to version up your Component with each Gaffer version.&lt;br /&gt;
&lt;br /&gt;
The first phase of a component build installs Gaffer. It first downloads Gaffer from the Github release URL. Then it extracts the archive to the &amp;lt;code&amp;gt;/opt&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
The extraction step makes use of another helpful feature in Component scripts - referencing variables from a previous step. The &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{build.DownloadGaffer.inputs[0].destination}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; text indicates that the file path to extract is taken from the &amp;lt;code&amp;gt;DownloadGaffer&amp;lt;/code&amp;gt; step of the &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; phase. This is another way to reduce errors from typos in your script.&lt;br /&gt;
&lt;br /&gt;
=== Arnold Component ===&lt;br /&gt;
&lt;br /&gt;
=== Gaffer Prerequisites Component ===&lt;br /&gt;
&lt;br /&gt;
=== Image Recipe ===&lt;br /&gt;
&lt;br /&gt;
=== Image Pipeline ===&lt;br /&gt;
Choose Image Pipelines to see the list of Pipelines, which is empty if this is your first time using it.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create Image Pipeline&amp;quot; to get started.&lt;br /&gt;
# Enter a name for the pipeline and optionally a description.&lt;br /&gt;
# Change the schedule option to &amp;quot;Manual&amp;quot; so it will only run when you trigger it.&lt;br /&gt;
# Proceed to the next step, to configure the Recipe.&lt;br /&gt;
# Choose &amp;quot;Create new recipe&amp;quot;. You will be given a variety of new options.&lt;br /&gt;
# Set the Image type to &amp;quot;Amazon Machine Image (AMI)&amp;quot;.&lt;br /&gt;
# Enter a name for the Recipe.&lt;br /&gt;
# Enter a version for the Recipe, such as &amp;lt;code&amp;gt;1.0.0&amp;lt;/code&amp;gt;.&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=308</id>
		<title>Installing Gaffer on AWS with EC2 Image Builder</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=308"/>
		<updated>2024-06-19T20:27:43Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a guide to setting up Amazon Web Services EC2 Image Builder with Gaffer. The EC2 Image Builder is a service from AWS that allows you to create an &#039;&#039;&#039;AMI&#039;&#039;&#039; (Amazon Machine Image) for use with EC2 with all the software and configuration needed to run jobs on AWS. An &#039;&#039;&#039;EC2 instance&#039;&#039;&#039; is a preset configuration of processor, memory and network resources made available by AWS - the virtual equivalent of hardware. An EC2 instance needs to be launched with an AMI that defines the virtual machine that will be running - the operating system and installed software.&lt;br /&gt;
&lt;br /&gt;
This guide is intended for users with some AWS knowledge but not expert level. After completing this guide, you will have a Linux-based EC2 AMI available to your AWS users that can be run on any EC2 instance type for running Gaffer tasks, including Arnold rendering. These instances can be launched manually through the AWS management console, via Python scripts or the AWS terminal, or from applications like Thinkbox&#039;s Deadline.&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
The EC2 Image Builder is split into a number of different parts. We need to work with three of those to create our Gaffer image. [https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html &#039;&#039;&#039;Image Pipelines&#039;&#039;&#039;] are run to create the AMI. With Image Pipelines, you determine the schedule with which it will be run (likely Manual for our purposes) and the Image Recipe that will be used to create the AMI.&lt;br /&gt;
&lt;br /&gt;
An &#039;&#039;&#039;[https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-recipes.html Image Recipe]&#039;&#039;&#039; consists the the base image AMI that will be the starting point for the new AMI, optional additional storage to attach to the instance and a set of components that define the software to be installed.&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;&#039;[https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-components.html Component]&#039;&#039;&#039; is a YAML script describing the set of steps to be performed to install and configure some logical unit of software.&lt;br /&gt;
&lt;br /&gt;
Image Recipes and Components are both versioned. When you save, that version becomes immutable and you will create a new version when making changes or fixes.&lt;br /&gt;
&lt;br /&gt;
=== Getting Started ===&lt;br /&gt;
To start, log into the AWS Console. Pay attention to the region you have set - this setting is in the top-right of the console. The EC2 Image Builder components as well as the generated AMIs (and therefore the EC2 instances you launch with them) are unique per-region.&lt;br /&gt;
&lt;br /&gt;
Choose EC2 Image Builder from the Services menu in the top-left. You can navigate between Image Pipelines, Image Recipes and Components from the left-side menu.&lt;br /&gt;
&lt;br /&gt;
=== Gaffer Component ===&lt;br /&gt;
From the navigation menu, choose Components to see a list of your customized components, which is empty if this is your first time using it.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create component&amp;quot;.&lt;br /&gt;
# Keep &amp;quot;Component type&amp;quot; set to &amp;lt;code&amp;gt;Build&amp;lt;/code&amp;gt;&lt;br /&gt;
# Set the Component Details&lt;br /&gt;
## Choose &amp;lt;code&amp;gt;Linux&amp;lt;/code&amp;gt; as the &amp;quot;Image operating system&amp;quot;. This indicates this recipe is compatible with Linux-based Image Pipelines. You determine the operating system for your AMI in the Image Pipeline configuration.&lt;br /&gt;
## From &amp;quot;Compatible OS Versions&amp;quot;, choose the Linux versions you intend for this recipe to be compatible with.&lt;br /&gt;
## Enter a Component name.&lt;br /&gt;
## Enter a Component version, such as &amp;lt;code&amp;gt;1.0.0&amp;lt;/code&amp;gt;&lt;br /&gt;
# Set the Content. This is the YAML script that will be run to install Gaffer. The following YAML script will setup Gaffer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name: Gaffer Component&lt;br /&gt;
description: Installs Gaffer for running on AWS EC2 instances.&lt;br /&gt;
schemaVersion: 1.0&lt;br /&gt;
&lt;br /&gt;
parameters:&lt;br /&gt;
  - gafferVersion:&lt;br /&gt;
      type: string&lt;br /&gt;
      default: &#039;1.3.7.0&#039;&lt;br /&gt;
      description: &#039;The Gaffer version to install.&#039;&lt;br /&gt;
  &lt;br /&gt;
phases:&lt;br /&gt;
  - name: build&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: DownloadGaffer&lt;br /&gt;
        action: WebDownload&lt;br /&gt;
        inputs:&lt;br /&gt;
          - source: https://github.com/GafferHQ/gaffer/releases/download/{{gafferVersion}}/gaffer-{{gafferVersion}}-linux.tar.gz&lt;br /&gt;
            destination: /tmp/gaffer-{{gafferVersion}}/gaffer-{{gafferVersion}}.tar.gz&lt;br /&gt;
&lt;br /&gt;
      - name: ExtractGaffer&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - tar xvzf {{build.DownloadGaffer.inputs[0].destination}} --strip-components=1 -C /tmp/gaffer-{{gafferVersion}}&lt;br /&gt;
            - rm {{build.DownloadGaffer.inputs[0].destination}}&lt;br /&gt;
&lt;br /&gt;
  - name: validate&lt;br /&gt;
    steps:&lt;br /&gt;
      - name: ValidateGaffer&lt;br /&gt;
        action: ExecuteBash&lt;br /&gt;
        inputs:&lt;br /&gt;
          commands:&lt;br /&gt;
            - /tmp/gaffer-{{gafferVersion}}/bin/gaffer env python -c &amp;quot;print(&#039;Gaffer validated&#039;)&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== Arnold Component ===&lt;br /&gt;
&lt;br /&gt;
=== Gaffer Prerequisites Component ===&lt;br /&gt;
&lt;br /&gt;
=== Image Recipe ===&lt;br /&gt;
&lt;br /&gt;
=== Image Pipeline ===&lt;br /&gt;
Choose Image Pipelines to see the list of Pipelines, which is empty if this is your first time using it.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create Image Pipeline&amp;quot; to get started.&lt;br /&gt;
# Enter a name for the pipeline and optionally a description.&lt;br /&gt;
# Change the schedule option to &amp;quot;Manual&amp;quot; so it will only run when you trigger it.&lt;br /&gt;
# Proceed to the next step, to configure the Recipe.&lt;br /&gt;
# Choose &amp;quot;Create new recipe&amp;quot;. You will be given a variety of new options.&lt;br /&gt;
# Set the Image type to &amp;quot;Amazon Machine Image (AMI)&amp;quot;.&lt;br /&gt;
# Enter a name for the Recipe.&lt;br /&gt;
# Enter a version for the Recipe, such as &amp;lt;code&amp;gt;1.0.0&amp;lt;/code&amp;gt;.&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=307</id>
		<title>Installing Gaffer on AWS with EC2 Image Builder</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=307"/>
		<updated>2024-06-19T20:11:50Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a guide to setting up Amazon Web Services EC2 Image Builder with Gaffer. The EC2 Image Builder is a service from AWS that allows you to create an &#039;&#039;&#039;AMI&#039;&#039;&#039; (Amazon Machine Image) for use with EC2 with all the software and configuration needed to run jobs on AWS. An &#039;&#039;&#039;EC2 instance&#039;&#039;&#039; is a preset configuration of processor, memory and network resources made available by AWS - the virtual equivalent of hardware. An EC2 instance needs to be launched with an AMI that defines the virtual machine that will be running - the operating system and installed software.&lt;br /&gt;
&lt;br /&gt;
This guide is intended for users with some AWS knowledge but not expert level. After completing this guide, you will have a Linux-based EC2 AMI available to your AWS users that can be run on any EC2 instance type for running Gaffer tasks, including Arnold rendering. These instances can be launched manually through the AWS management console, via Python scripts or the AWS terminal, or from applications like Thinkbox&#039;s Deadline.&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
The EC2 Image Builder is split into a number of different parts. We need to work with three of those to create our Gaffer image. [https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html &#039;&#039;&#039;Image Pipelines&#039;&#039;&#039;] are run to create the AMI. With Image Pipelines, you determine the schedule with which it will be run (likely Manual for our purposes) and the Image Recipe that will be used to create the AMI.&lt;br /&gt;
&lt;br /&gt;
An &#039;&#039;&#039;[https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-recipes.html Image Recipe]&#039;&#039;&#039; consists the the base image AMI that will be the starting point for the new AMI, optional additional storage to attach to the instance and a set of components that define the software to be installed.&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;&#039;[https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-components.html Component]&#039;&#039;&#039; is a YAML script describing the set of steps to be performed to install and configure some logical unit of software.&lt;br /&gt;
&lt;br /&gt;
Image Recipes and Components are both versioned. When you save, that version becomes immutable and you will create a new version when making changes or fixes.&lt;br /&gt;
&lt;br /&gt;
=== Getting Started ===&lt;br /&gt;
To start, log into the AWS Console. Pay attention to the region you have set - this setting is in the top-right of the console. The EC2 Image Builder components as well as the generated AMIs (and therefore the EC2 instances you launch with them) are unique per-region.&lt;br /&gt;
&lt;br /&gt;
Choose EC2 Image Builder from the Services menu in the top-left. You can navigate between Image Pipelines, Image Recipes and Components from the left-side menu.&lt;br /&gt;
&lt;br /&gt;
=== Gaffer Component ===&lt;br /&gt;
&lt;br /&gt;
=== Arnold Component ===&lt;br /&gt;
&lt;br /&gt;
=== Gaffer Prerequisites Component ===&lt;br /&gt;
&lt;br /&gt;
=== Image Recipe ===&lt;br /&gt;
&lt;br /&gt;
=== Image Pipeline ===&lt;br /&gt;
Choose Image Pipelines to see the list of Pipelines, which is empty if this is your first time using it.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create Image Pipeline&amp;quot; to get started.&lt;br /&gt;
# Enter a name for the pipeline and optionally a description.&lt;br /&gt;
# Change the schedule option to &amp;quot;Manual&amp;quot; so it will only run when you trigger it.&lt;br /&gt;
# Proceed to the next step, to configure the Recipe.&lt;br /&gt;
# Choose &amp;quot;Create new recipe&amp;quot;. You will be given a variety of new options.&lt;br /&gt;
# Set the Image type to &amp;quot;Amazon Machine Image (AMI)&amp;quot;.&lt;br /&gt;
# Enter a name for the Recipe.&lt;br /&gt;
# Enter a version for the Recipe, such as &amp;lt;code&amp;gt;1.0.0&amp;lt;/code&amp;gt;.&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=306</id>
		<title>Installing Gaffer on AWS with EC2 Image Builder</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=306"/>
		<updated>2024-06-19T20:06:42Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a guide to setting up Amazon Web Services EC2 Image Builder with Gaffer. The EC2 Image Builder is a service from AWS that allows you to create an &#039;&#039;&#039;AMI&#039;&#039;&#039; (Amazon Machine Image) for use with EC2 with all the software and configuration needed to run jobs on AWS. An &#039;&#039;&#039;EC2 instance&#039;&#039;&#039; is a preset configuration of processor, memory and network resources made available by AWS - the virtual equivalent of hardware. An EC2 instance needs to be launched with an AMI that defines the virtual machine that will be running - the operating system and installed software.&lt;br /&gt;
&lt;br /&gt;
This guide is intended for users with some AWS knowledge but not expert level. After completing this guide, you will have a Linux-based EC2 AMI available to your AWS users that can be run on any EC2 instance type for running Gaffer tasks, including Arnold rendering. These instances can be launched manually through the AWS management console, via Python scripts or the AWS terminal, or from applications like Thinkbox&#039;s Deadline.&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
The EC2 Image Builder is split into a number of different parts. We need to work with three of those to create our Gaffer image. [https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html &#039;&#039;&#039;Image Pipelines&#039;&#039;&#039;] are run to create the AMI. With Image Pipelines, you determine the schedule with which it will be run (likely Manual for our purposes) and the Image Recipe that will be used to create the AMI.&lt;br /&gt;
&lt;br /&gt;
An &#039;&#039;&#039;[https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-recipes.html Image Recipe]&#039;&#039;&#039; consists the the base image AMI that will be the starting point for the new AMI, optional additional storage to attach to the instance and a set of components that define the software to be installed.&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;&#039;[https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-components.html Component]&#039;&#039;&#039; is a YAML script describing the set of steps to be performed to install and configure some logical unit of software.&lt;br /&gt;
&lt;br /&gt;
Image Recipes and Components are both versioned. When you save, that version becomes immutable and you will create a new version when making changes or fixes.&lt;br /&gt;
&lt;br /&gt;
=== Image Pipeline ===&lt;br /&gt;
To start, log into the AWS Console. Pay attention to the region you have set - this setting is in the top-right of the console. The EC2 Image Builder components as well as the generated AMIs (and therefore the EC2 instances you launch with them) are unique per-region.&lt;br /&gt;
&lt;br /&gt;
Choose EC2 Image Builder from the Services menu in the top-left.&lt;br /&gt;
&lt;br /&gt;
You can navigate between Image Pipelines, Image Recipes and Components from the left-side menu. Choose Image Pipelines to see the list of Pipelines, which is empty if this is your first time using it.&lt;br /&gt;
&lt;br /&gt;
# Choose &amp;quot;Create Image Pipeline&amp;quot; to get started.&lt;br /&gt;
# Enter a name for the pipeline and optionally a description.&lt;br /&gt;
# Change the schedule option to &amp;quot;Manual&amp;quot; so it will only run when you trigger it.&lt;br /&gt;
# Proceed to the next step, to configure the Recipe.&lt;br /&gt;
# Choose &amp;quot;Create new recipe&amp;quot;. You will be given a variety of new options.&lt;br /&gt;
# Set the Image type to &amp;quot;Amazon Machine Image (AMI)&amp;quot;.&lt;br /&gt;
# Enter a name for the Recipe.&lt;br /&gt;
# Enter a version for the Recipe, such as `1.0.0`.&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=305</id>
		<title>Installing Gaffer on AWS with EC2 Image Builder</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Installing_Gaffer_on_AWS_with_EC2_Image_Builder&amp;diff=305"/>
		<updated>2024-06-19T19:21:36Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: Created page with &amp;quot;This is a guide to setting up Amazon Web Services EC2 Image Builder with Gaffer. The EC2 Image Builder is a service from AWS that allows you to create AMIs (Amazon Machine Images) for use with EC2 with all the software and configuration needed to run jobs on AWS.  This guide is intended for users with some AWS knowledge but not expert level. After completing this guide, you will have an EC2 AMI available to your AWS users that can be run on any EC2 instance type for runn...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a guide to setting up Amazon Web Services EC2 Image Builder with Gaffer. The EC2 Image Builder is a service from AWS that allows you to create AMIs (Amazon Machine Images) for use with EC2 with all the software and configuration needed to run jobs on AWS.&lt;br /&gt;
&lt;br /&gt;
This guide is intended for users with some AWS knowledge but not expert level. After completing this guide, you will have an EC2 AMI available to your AWS users that can be run on any EC2 instance type for running Gaffer tasks. These instances can be launched manually through the AWS management console, via Python scripts or AWS terminals, or from applications like Thinkbox&#039;s Deadline.&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
The EC2 Image Builder is split into number of different parts. We need to work with three of those to create our Gaffer image. Image Pipelines are what&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=Main_Page&amp;diff=304</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=Main_Page&amp;diff=304"/>
		<updated>2024-06-19T18:55:54Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Gaffer Wiki}} &lt;br /&gt;
=Welcome to Gaffer Wiki=&lt;br /&gt;
&lt;br /&gt;
Gaffer Wiki is a community effort and everyone is welcome to contribute. Here you can find [[:Category:Examples|Examples]], Templates, Guides and more for [https://www.gafferhq.org Gaffer]. See [[Help:Getting started|Getting started]] if this is your first time contributing.&lt;br /&gt;
&lt;br /&gt;
== Getting Started With Gaffer ==&lt;br /&gt;
&lt;br /&gt;
If you&#039;re completely new to Gaffer, begin with [[Getting started with Gaffer]].&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
[[:Category:Examples|Examples]] provide small snippets of functionality to demonstrate how to do useful things with Gaffer&#039;s [[:Category:Nodes|Nodes]].&lt;br /&gt;
&lt;br /&gt;
== Templates ==&lt;br /&gt;
&lt;br /&gt;
Templates are more complete scripts, useful as a jumping off point for creating your own Gaffer setups.&lt;br /&gt;
&lt;br /&gt;
== Guides ==&lt;br /&gt;
&lt;br /&gt;
Guides go more in depth into specific aspects of Gaffer. From usage through to customising and extending Gaffer.&lt;br /&gt;
&lt;br /&gt;
* [[Installing Gaffer on AWS with EC2 Image Builder]]&lt;br /&gt;
&lt;br /&gt;
== External Resources ==&lt;br /&gt;
&lt;br /&gt;
[https://www.gafferhq.org/documentation Gaffer&#039;s Documentation]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/gafferHQ/gaffer Gaffer GitHub]&lt;br /&gt;
&lt;br /&gt;
[https://www.gafferhq.org/resources GafferHQ Resources]&lt;br /&gt;
&lt;br /&gt;
[https://groups.google.com/g/gaffer-dev Gaffer-Dev Mailing List]&lt;br /&gt;
&lt;br /&gt;
[https://discord.gg/sEm8dDw Gaffer Users Discord]&lt;br /&gt;
&lt;br /&gt;
__NOTOC__&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=ScatterSamplePrimitiveVariables&amp;diff=303</id>
		<title>ScatterSamplePrimitiveVariables</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=ScatterSamplePrimitiveVariables&amp;diff=303"/>
		<updated>2024-06-19T15:28:21Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: Added Featured Nodes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Example&lt;br /&gt;
|description=An example of sampling the base surface with a `Scatter` node. In this example, the normals of the surface are sampled onto the scattered points and are used to orient the scattered GafferBots. An additional Z direction is also calculated to make the instanced bots face a focal point.&lt;br /&gt;
|file=ScatterSampleSurface.gfr&lt;br /&gt;
|screenshots=ScatterSampleSurface.jpg&lt;br /&gt;
|categories=Scatter&lt;br /&gt;
|nodes=Scatter, Instancer}}&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=ScatterSamplePrimitiveVariables&amp;diff=302</id>
		<title>ScatterSamplePrimitiveVariables</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=ScatterSamplePrimitiveVariables&amp;diff=302"/>
		<updated>2024-06-19T15:19:00Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: Demonstrates sampling primitive variables in a Scatter node.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Example&lt;br /&gt;
|description=An example of sampling the base surface with a `Scatter` node. In this example, the normals of the surface are sampled onto the scattered points and are used to orient the scattered GafferBots. An additional Z direction is also calculated to make the instanced bots face a focal point.&lt;br /&gt;
|file=ScatterSampleSurface.gfr&lt;br /&gt;
|screenshots=ScatterSampleSurface.jpg&lt;br /&gt;
|categories=Scatter&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=File:ScatterSampleSurface.jpg&amp;diff=301</id>
		<title>File:ScatterSampleSurface.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=File:ScatterSampleSurface.jpg&amp;diff=301"/>
		<updated>2024-06-19T15:17:56Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
	<entry>
		<id>https://www.gaffer.wiki/w/index.php?title=File:ScatterSampleSurface.gfr&amp;diff=300</id>
		<title>File:ScatterSampleSurface.gfr</title>
		<link rel="alternate" type="text/html" href="https://www.gaffer.wiki/w/index.php?title=File:ScatterSampleSurface.gfr&amp;diff=300"/>
		<updated>2024-06-19T15:13:02Z</updated>

		<summary type="html">&lt;p&gt;Ericmehl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ericmehl</name></author>
	</entry>
</feed>