Coder Social home page Coder Social logo

imagr's Introduction

Imagr is an application designed to be run from a NetInstall environment created with AutoNBI. It is able replace tools such as DeployStudio for many organisations without the requirement of needing to be run on OS X servers.

This is a Python application, so Python will need to be included in your NetInstall.

Development Mailing List: imagr-dev

Support Mailing List: imagr-discuss

Getting Started

The best place to get started with Imagr is the Getting Started page on the wiki.

Features

  • Restore ASR Images (such as those created with AutoDMG)
  • Install macOS via startosinstall
  • Install packages during Imagr run and at first boot
  • Run scripts during Imagr run and at first boot
  • Include other workflows in your workflow, specified statically or using a script
  • Erase and partition disks
  • Rename the machine
  • Protect your users from accidentally wiping their devices by specifying a password for Imagr

imagr's People

Contributors

0xcedb avatar 128keaton avatar a-zaleski avatar bruienne avatar chilcote avatar chrisgrande avatar clburlison avatar clkw0rk avatar davelebbing avatar dhmoore avatar erikng avatar grahamgilbert avatar gregneagle avatar groob avatar jazaval avatar kylecrawshaw avatar larkost avatar macmule avatar magervalp avatar mosen avatar n8felton avatar nmcspadden avatar pickmansec avatar poundbangbash avatar rdrake avatar rmanly avatar tburgin avatar timsutton avatar twocanoes avatar vmiller avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

imagr's Issues

The road to 0.0.1

I've been amazed with the speed we've got Imagr from my crappy code to something useful, so I thought it would be helpful to start thinking about what is left to do before we can do an initial release. In my opinion, we need to:

  • Adjust the Makefile to build an NBI from the GitHub release rather than the development code
  • Fully document the options (probably move to the Wiki for this rather than the ever expanding Readme)
  • A tool that will validate the configuration plist's syntax

Anything else?

Clicking on Workflow Description changes selected Workflow

Steps to reproduce:

  1. Have a config plist with more than one workflow
  2. Upon login select a workflow other than the first workflow
  3. Click in the "Workflow Description" field

Result: Selected workflow resets to the first workflow in the config.

This actually happens when you click on in the description field on the first workflow but cannot visually see it happen.

Add json as a configuration file type

Because this is running on Linux and is hosted on a web server, it would be good to support json as a config file format.

One could imagine a web server piece that dynamically serves up the json file based upon various conditions (the netboot set location, some sort of fact, etc). Obviously this would be left up to the person implementing their imagr server.

I think using plist is fine because admins are familiar with it, but json is far more common on web servers and are even supported by the default python install on almost everything.

Add include workflow task

It would be nice to be able to include a workflow by name to another workflow.
Perhaps this would be best implemented if there was a hidden flag in the top dictionary of workflows.
So we can create workflows only meant for inclusion.

Workflow failure does not allow retry.

If Imagr fails to pull down any component of the workflow, you do not have the ability to retry. You can hit "OK" Which will then bring up Startup Disk. Imagr is blank and only allows you to quit. Quitting Imagr (when using AutoNBI) causes it to load the normal recovery.

reporting crash

I know you just added the feature...When the reporturl key is set to the login page of your imagr-server, Imagr will hard crash. All other "random" variations I could come up with silently failed with the correct error message (time-out, server not available, etc.).

2015-06-10 17:56:55.292 Imagr[7869:61825] gurl options: {
    file = "/tmp/tempdata";
    "follow_redirects" = 0;
    "logging_function" = "<objc.function 'NSLog' at 0x10a904cf0>";
    "post_data" = "status=in_progress&serial=A12BCDE3FG45&message=Imagr+is+starting+up...";
    url = "http://imagr:8000/";
}
2015-06-10 17:56:55.437 Imagr[7869:61825] An uncaught exception was raised
2015-06-10 17:56:55.437 Imagr[7869:61825] <type 'exceptions.ValueError'>: Too few arguments for format string [cur:1/len:1]
2015-06-10 17:56:55.438 Imagr[7869:61825] (
    0   CoreFoundation                      0x00007fff909a831c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff83d07c48 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff909a7eb9 -[NSException raise] + 9
    3   _objc.so                            0x000000010a34aba4 PyObjCErr_ToObjCWithGILState + 46
    4   _objc.so                            0x000000010a337792 PyObjCFFI_MakeClosure + 5033
    5   libffi.dylib                        0x00007fff858b9a24 ffi_closure_unix64_inner + 516
    6   libffi.dylib                        0x00007fff858b9096 ffi_closure_unix64 + 70
    7   CFNetwork                           0x00007fff854f47b2 -[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:] + 233
    8   CFNetwork                           0x00007fff854f46b7 -[NSURLConnectionInternal _withActiveConnectionAndDelegate:] + 48
    9   CFNetwork                           0x00007fff854f53d4 _ZL30_NSURLConnectionDidReceiveDataP16_CFURLConnectionPK8__CFDatalPKv + 79
    10  CFNetwork                           0x00007fff854f5067 ___ZN27URLConnectionClient_Classic29_delegate_didReceiveDataArrayEv_block_invoke + 293
    11  CFNetwork                           0x00007fff855cf7cd ___ZN27URLConnectionClient_Classic18_withDelegateAsyncEPKcU13block_pointerFvP16_CFURLConnectionPK33CFURLConnectionClientCurrent_VMaxE_block_invoke_2 + 100
    12  libdispatch.dylib                   0x00007fff8d7d1383 _dispatch_client_callout + 8
    13  libdispatch.dylib                   0x00007fff8d7e7672 _dispatch_block_invoke + 474
    14  CFNetwork                           0x00007fff854508c4 _ZN19RunloopBlockContext13_invoke_blockEPKvPv + 24
    15  CoreFoundation                      0x00007fff90886594 CFArrayApplyFunction + 68
    16  CFNetwork                           0x00007fff854507bd _ZN19RunloopBlockContext7performEv + 137
    17  CFNetwork                           0x00007fff85450598 _ZN17MultiplexerSource7performEv + 282
    18  CFNetwork                           0x00007fff854503ba _ZN17MultiplexerSource8_performEPv + 72
    19  CoreFoundation                      0x00007fff908b97a1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    20  CoreFoundation                      0x00007fff908abf9c __CFRunLoopDoSources0 + 556
    21  CoreFoundation                      0x00007fff908ab4bf __CFRunLoopRun + 927
    22  CoreFoundation                      0x00007fff908aaeb8 CFRunLoopRunSpecific + 296
    23  Foundation                          0x00007fff8f8dfd42 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 270
    24  Foundation                          0x00007fff8f8fd677 -[NSRunLoop(NSRunLoop) runUntilDate:] + 108
    25  libffi.dylib                        0x00007fff858b8f14 ffi_call_unix64 + 76
    26  ???                                 0x00007fb9777bef90 0x0 + 140434550288272
)
2015-06-10 17:56:55.438 Imagr[7869:61825] *** Terminating app due to uncaught exception 'OC_PythonException', reason: '<type 'exceptions.ValueError'>: Too few arguments for format string [cur:1/len:1]'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff909a831c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff83d07c48 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff909a7eb9 -[NSException raise] + 9
    3   _objc.so                            0x000000010a34aba4 PyObjCErr_ToObjCWithGILState + 46
    4   _objc.so                            0x000000010a337792 PyObjCFFI_MakeClosure + 5033
    5   libffi.dylib                        0x00007fff858b9a24 ffi_closure_unix64_inner + 516
    6   libffi.dylib                        0x00007fff858b9096 ffi_closure_unix64 + 70
    7   CFNetwork                           0x00007fff854f47b2 -[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:] + 233
    8   CFNetwork                           0x00007fff854f46b7 -[NSURLConnectionInternal _withActiveConnectionAndDelegate:] + 48
    9   CFNetwork                           0x00007fff854f53d4 _ZL30_NSURLConnectionDidReceiveDataP16_CFURLConnectionPK8__CFDatalPKv + 79
    10  CFNetwork                           0x00007fff854f5067 ___ZN27URLConnectionClient_Classic29_delegate_didReceiveDataArrayEv_block_invoke + 293
    11  CFNetwork                           0x00007fff855cf7cd ___ZN27URLConnectionClient_Classic18_withDelegateAsyncEPKcU13block_pointerFvP16_CFURLConnectionPK33CFURLConnectionClientCurrent_VMaxE_block_invoke_2 + 100
    12  libdispatch.dylib                   0x00007fff8d7d1383 _dispatch_client_callout + 8
    13  libdispatch.dylib                   0x00007fff8d7e7672 _dispatch_block_invoke + 474
    14  CFNetwork                           0x00007fff854508c4 _ZN19RunloopBlockContext13_invoke_blockEPKvPv + 24
    15  CoreFoundation                      0x00007fff90886594 CFArrayApplyFunction + 68
    16  CFNetwork                           0x00007fff854507bd _ZN19RunloopBlockContext7performEv + 137
    17  CFNetwork                           0x00007fff85450598 _ZN17MultiplexerSource7performEv + 282
    18  CFNetwork                           0x00007fff854503ba _ZN17MultiplexerSource8_performEPv + 72
    19  CoreFoundation                      0x00007fff908b97a1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    20  CoreFoundation                      0x00007fff908abf9c __CFRunLoopDoSources0 + 556
    21  CoreFoundation                      0x00007fff908ab4bf __CFRunLoopRun + 927
    22  CoreFoundation                      0x00007fff908aaeb8 CFRunLoopRunSpecific + 296
    23  Foundation                          0x00007fff8f8dfd42 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 270
    24  Foundation                          0x00007fff8f8fd677 -[NSRunLoop(NSRunLoop) runUntilDate:] + 108
    25  libffi.dylib                        0x00007fff858b8f14 ffi_call_unix64 + 76
    26  ???                                 0x00007fb9777bef90 0x0 + 140434550288272
)
libc++abi.dylib: terminating with uncaught exception of type NSException
make: *** [run] Error 134

COSXIP Fails to install in an AutoNBI generated NBI

Not an issue with Imagr, but writing it down here so I remember to follow it up. Imagr works when used with a DeployStudio NBI, so something is missing that is causing the postinstall script to fail. Need to find out what it is and put it in AutoNBI.

Config plist validation

If the configuration plist is not properly formatted, Imagr will crash. Should validate and present an error message.

  • tag validation 16fb581
  • two workflows with same name 55be9d4
  • Currently possible to have multiple password keys (see comment below)

Small visual bug on Target Selection

I have only seen this happen on physical clients and even then only a handful of times. After typing the password the main window loads however the "Choice Target" is blank. These machines only have one partition and Imagr is successfully resolving that partition (you are able to run the workflow with success). However the GUI element does not display the currently selected target disk.

Out of 40 clients (50 more tomorrow) I have seen this happen 4 times so enough that something is funky.

Build 240. Using AutoNBI NetInstall environment.

I can try and get more debug info if need just have to finish this roll out first.

A way to suppress restart at the end of a workflow

This could take the form of a preference, or a key in the workflow.

When testing, it's helpful to be able to verify the results of a workflow before the restart occurs; I can just comment out the restart action in code right now, but would be nice to have more formal support.

Please look at my fork

Just opening an issue so this doesn't get forgotten

https://github.com/gregneagle/imagr

If you like the direction, I can open a pull request.

Main changes:

  1. Imagr subscribes to NSWorkspace notifications to be notified when a new volume is mounted, an existing volume is unmounted, or a volume is renamed.

  2. Target disk selection is moved to a popup menu in the same view as the workflow selection.

  3. Other UI elements moved in the workflow selection view: Run Workflow moved to lower right, where an OK, Save, or other default "Perform the action" button is usually located in dialogs and assistant-type utilties. Other elements moved to adjust.

Cloning Error when dmg url is incorrect

Imagr will present a cloning error dialog, which you can hit OK to and then reboot/select startup disk

Imagr should take you back to the workflow selection (this is similar to #64 )

Makefile Validate

I'm not sure it is necessary to include the validateplist script with the dmg. We are currently instructing users to git clone the repo from the wiki which will download the most up to date script.

Other thought would be to include the Makefile which allows users to avoid git clone altogether.

Not sure what best practice would be...Imagr is in early development so I'll let you decide.

Disable network check on first boot

The first boot script will wait for the network to be available before installing anything. The source script allows for this to be disabled, so we need to have a key in the workflow to let this be disabled.

Allow dynamic selection of image

The goal is to allow an arbitrary script to run and select which image to use during the apply image step. It does not need to be exactly as listed below, but having the functionality is super helpful, especially if you want one master workflow for support folks to run.

An example workflow:

  • You have a vanilla image that works on all machines except the new MacBook
  • You run a script to determine which machine type is netbooted
  • You output which image you would like to be applied
  • The Image task continues as usual

munki bootstrap is killed by reboots

my plist
https://gist.github.com/JDHatman/d90095854831359c9f1a

All pre_first_boot images/packages work.
All first_boot packages install successfully, one of which is a munki kickstart.
Before Imagr reboots from the first_boot installs, Munki has already started. Imagr reboots shortly into the Munki run.
After the reboot, Munki runs again. There is a second reboot, for no apparent reason. Again, interrupting the Munki run.
After the second reboot, the kickstart I initiated for Munki has just given up and Munki doesn't run. This leaves the computer is a pretty useless state since Munki installs all the relevant bits like accounts and such.
I can boot into Recovery and manually re-touch .com.googlecode.munki.checkandinstallatstartup and after rebooting Munki will run as expected and "finish" my imaging process.

I have two workflows. I noticed that the same pattern occurs when I use only the kickstart workflow (assuming there is a usable image already on the machine). However, using this workflow, the Munki run will continue even after getting interrupted by two reboots.

I realize that this isn't necessarily an issue with Imagr. More or less providing info from my experiences.

LoginLog opens even when there are no firstboot packages installed.

here is the workflow I tested this with:

    <dict>
      <key>name</key>
      <string>Mavericks - MunkiTools</string>
      <key>description</key>
      <string>Deploys the latest 10.9.x image. Munki tools and local admin account included.</string>
      <key>components</key>
      <array>
        <dict>
          <key>type</key>
          <string>image</string>
          <key>url</key>
          <string>http://imagr.whitbyschool.net/images/osx_custom_141014-10.9.5-13F34.hfs.dmg</string>
        </dict>
      </array>
      <key>restart_action</key>
      <string>restart</string>
    </dict>

The firstboot log opened at the same time as MSC.

UI reorg

I didn't make this a pull list because it might be not a direction you are interested in.

gregneagle@2719ef0

This moves the login and main views into a tab view, which makes switching views easier, and allows us to add more views without going crazy trying to edit them in InterfaceBuilder.

As an example I added a new startup view that replaces the sheet.

It might be nice to add an "empty" view or "error" view we switch to when we don't find a server url or any writable volumes, etc. (instead of trying to hide all the controls, etc)

Since this is a pretty dramatic set of changes I thought I'd let you look at my clone first before deciding if this is a direction that makes sense.

(There's additional cleanup to be done if you decide this is a direction you want to go, but I don't want to do all the cleanup work if you don't want to go this way.)

Uncaught exception LoginLog.app

If you run two workflows back-to-back it is currently possible for the LoginLog.app to be copied to the system twice causing a crash.

Error log

<type 'exceptions.OSError'>: [Errno 17] File exists: '/Library/PrivilegedHelperTools/LoginLog.app'
2015-04-26 12:40:43.968 Imagr[52121:2394065] (
    0   CoreFoundation                      0x00007fff94bb503c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff89fb576e objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff94bb4bd9 -[NSException raise] + 9
    3   _objc.so                            0x0000000106431a8b PyObjCErr_ToObjCWithGILState + 46
    4   _objc.so                            0x000000010641e52d PyObjCFFI_MakeClosure + 5097
    5   libffi.dylib                        0x00007fff95468a07 ffi_closure_unix64_inner + 511
    6   libffi.dylib                        0x00007fff954680c6 ffi_closure_unix64 + 70
    7   libsystem_pthread.dylib             0x00007fff8ecd6268 _pthread_body + 131
    8   libsystem_pthread.dylib             0x00007fff8ecd61e5 _pthread_body + 0
    9   libsystem_pthread.dylib             0x00007fff8ecd441d thread_start + 13
)
2015-04-26 12:40:43.968 Imagr[52121:2394065] *** Terminating app due to uncaught exception 'OC_PythonException', reason: '<type 'exceptions.OSError'>: [Errno 17] File exists: '/Library/PrivilegedHelperTools/LoginLog.app''
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff94bb503c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff89fb576e objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff94bb4bd9 -[NSException raise] + 9
    3   _objc.so                            0x0000000106431a8b PyObjCErr_ToObjCWithGILState + 46
    4   _objc.so                            0x000000010641e52d PyObjCFFI_MakeClosure + 5097
    5   libffi.dylib                        0x00007fff95468a07 ffi_closure_unix64_inner + 511
    6   libffi.dylib                        0x00007fff954680c6 ffi_closure_unix64 + 70
    7   libsystem_pthread.dylib             0x00007fff8ecd6268 _pthread_body + 131
    8   libsystem_pthread.dylib             0x00007fff8ecd61e5 _pthread_body + 0
    9   libsystem_pthread.dylib             0x00007fff8ecd441d thread_start + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Optional script task name

(this is so I don't forget).

Optional feature for script task names to allow more verbose messaging for Imagr-server.

Unified "runWorkflowOnThread" method

Since it seems like the goal is to provide meaningful progress feedback when a workflow runs, I think it might make more sense to build a single "runWorkflowOnThread" method that performs the various subtasks, updating the status display as it runs. This would eliminate a lot of code duplication for each of the 'doSubtaskOnThread" methods, and make it easier to do consistent progress feedback for the entire workflow.

disk mount notifications and possible UI change

Imagr should subscribe to the following NSWorkspace notifications: NSWorkspaceDidRenameVolumeNotification, NSWorkspaceDidMountNotification, NSWorkspaceWillUnmountNotification and NSWorkspaceDidUnmountNotification

This would allow for rescanning available volumes "automatically".

I also wonder if perhaps the selection of the target volume doesn't need to be modal, and could just be a pop-up menu on the workflows screen...

I'm envisioning someone running Imagr, sitting at the workflows screen, then opening Disk Utility and repartitioning, or plugging in a USB drive. It would be nice if Imagr "automatically" noticed the change in available volumes and updated its pop-up menu accordingly.

I can work on this if you'd like, though I may not get to it until Monday.

Option to rename computer

How do you feel about an optional text field that allows us to rename the computer on firstboot? Imagr could output a simple text file after the image process while your first-boot script could be modified to look for said file. That is the only missing feature that would allow me to drop DeployStudio.

Computer name change isn't working

I'm using the following in the workflow to prompt for computer name:

    <dict>
        <key>type</key>
        <string>computer_name</string>
    </dict>

The name is being set to iMac instead of the inputted name.. The OS the netinstall image was created on was OS X 10.10.4. The computers are the latest revision iMac's with fusion drives.

Not sure what logs to check to see what's it's trying to do.

Refresh button

It would be nice if new workflows could be viewed without quitting Imagr.

Imagr takes a very long time to startup: optimize/replace macdisk.MountedVolumes() ?

This might be NBI-dependent, but when testing on a DeployStudio NBI, Imagr takes upwards of 20+ seconds to become usable. A big chunk of that time is in macdisk.MountedVolumes().

Looking through the code, it ends up calling diskutil info -plist for every device id, which is incredibly slow.

I'd like to look at ways to speed this up.

launchApp improvements

Improve launchApp behavior if app is already running thusly:

  • Check if app is already running
  • If it is running, skip binary launch and just do NSWorkSpace.launchApplication to bring it to the front

When pre_first_boot script Components Fail, workflow Execution Doesn't Stop

When running a workflow with a pre_first_boot script component, if the pre_first_boot script exits non-zero (i.e. it fails) workflow execution continues and the user isn't notified the script failed.

An example workflow:

<dict>
  <key>name</key>
  <string>Test Script Error</string>
  <key>description</key>
  <string>Intentionally create an error in a script</string>
  <key>components</key>
  <array>
    <dict>
      <key>type</key>
      <string>script</string>
      <key>content</key>
      <string>#!/bin/bash ; exit 1</string>
      <key>pre_first_boot</key>
      <true/>
    </dict>
  </array>
  <key>restart_action</key>
  <string>none</string>
</dict>

Computer Name Field

The computer name field should be selected by default when the workflow opens the Computer Name view.

New Reload button and bad imagr_config.plist

Easy test. Add an extra undernearth a workflow and use the new Reload Workflows feature.

Imagr will hide all of the buttons and display a "No workflows found in the configuration plist" dialog box. After pressing "Okay" you are presented a blank Imagr with no buttons. Startup Disk will then open.

If you go back to Imagr (after fixing the plist) you can Command+R, but in my testing it still cannot resolve the .plist issue. Reloading Imagr/NBI will fix the issue.

Mount volume after ASR

Latest pull of Imagr does not mount the volume after DMG ASR.

You can easily test this with the following workflow:

<dict>
  <key>name</key>
  <string>Yosemite 10.10.3 Basic</string>
  <key>description</key>
  <string>This is a basic test image.</string>
  <key>components</key>
  <array>
    <dict>
      <key>type</key>
      <string>image</string>
      <key>url</key>
      <string>http://xxx/imagr/masters/OS_X_10.10.3-14D136.hfs.dmg</string>
    </dict> 
  </array>
</dict>

After finishing, the volume is not mounted. Imagr will also complain that it cannot find any volumes if you attempt to run another workflow.

More advanced workflows calling preboot scripts will cause Imagr to immediately hard crash.

<dict>
  <key>name</key>
  <string>Yosemite 10.10.3 Basic</string>
  <key>description</key>
  <string>This is a basic test image with preboot script.</string>
  <key>components</key>
  <array>
    <dict>
      <key>type</key>
      <string>image</string>
      <key>url</key>
      <string>http://xxx/imagr/masters/OS_X_10.10.3-14D136.hfs.dmg</string>
    </dict> 
    <dict>
        <key>type</key>
        <string>script</string>
        <key>content</key>
        <string>#!/bin/bash
    echo ""
    exit 0
        </string>
        <key>first_boot</key>
        <false/>
    </dict>  
  </array>
</dict>

Set $3 for script task

Hi, thanks for making imagr!
Were in the process of replacing DeployStudio with imagr and I have a few suggestions for improvements. I'm braking them up to different issues so you can consider them separately
It would be really nice if the $3 variable was set for script tasks.
I know i can use {{target_volume}} but it would be nice to be able to just use legacy scripts.

License

Please add a license to the project!

Apache is best =)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.