maschmann / php-ansible

php oop wrapper for ansible provisioning tool

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

execute() always returns null - Most definitely user error

goatatwork opened this issue · comments

Hello again,

Sorry to be a pain. I can not seem to get any output from the execute() method. Laravel 5.1 project. I have an index method in an AnsibleController.

This returns "null":
use Asm\Ansible\Ansible;
class AnsibleController extends Controller
{
public function index()
{
$ansible = new Ansible(
'/home/vagrant/Sites/goldaccess/resources/assets/ansible-playbook/',
'/usr/bin/ansible-playbook',
'/usr/bin/ansible-galaxy'
);
$output = $ansible->playbook()->play('test.yml')->execute();
dd($output);
return view('ansible.index');
}
}

And this one returns the ansible object:
use Asm\Ansible\Ansible;
class AnsibleController extends Controller
{
public function index()
{
$ansible = new Ansible(
'/home/vagrant/Sites/goldaccess/resources/assets/ansible-playbook/',
'/usr/bin/ansible-playbook',
'/usr/bin/ansible-galaxy'
);
$ansible->playbook()->play('test.yml')->execute();
dd($ansible);
return view('ansible.index');
}
}

..returns:
Ansible {#236 ▼
-playbookCommand: "/usr/bin/ansible-playbook"
-galaxyCommand: "/usr/bin/ansible-galaxy"
-ansibleBaseDir: "/home/vagrant/Sites/goldaccess/resources/assets/ansible-playbook/"
-timeout: 300
}

I can successfully execute the following AS the user that runs nginx:
/usr/bin/ansible-playbook /home/vagrant/Sites/goldaccess/resources/assets/ansible-playbook/test.yml

While this might be more "support request" than "issue report", it would be so very nice to know what you think I'm doing wrong.

Thank you in advance for any thoughts you have!

Have you tried something like that?
https://github.com/maschmann/php-deploy/blob/master/src/CoreBundle/Controller/PageController.php#L221

I'll have a look into it later, I'm currently migrating my server infrastructure :-( Therefore a bit lack of time

Thank you very very much. It looks like what I was not including was the inventoryFile.

$inventoryFile = '/etc/ansible/hosts';
$output = $ansible->playbook()->play('test.yml')->inventoryFile($inventoryFile)->execute();

That works!! I had omitted the inventoryFile() method! I still have some confusion about how to best handle success and failure of the commands, but I'm on the right path now and it is executing properly. My output is the string version of the output one would get on the command line (as you already know).

Just tested this a little more thoroughly. Looks good here. Thanks for your attention to this and the link to the sample code.

@goatatwork no problem there :-) I've developed the library to be handled by a deployment-platform, based on symfony. When I'm done with that, I'll provide a symfony bundle. Maybe that's usable in Laravel context, too.

Maybe this thread isn't the appropriate place to put this, but thought I'd share my controller class with you. Also, I might be approaching this sideways, but I was just looking to fire off the playbook, and then "know" if things went well or not as I move on to my view. This isn't ironed out, and if you see anything glaringly ridiculous here, I'd love to know. But here's where I landed for now (until I decide or figure out exactly what the application is going to do with it after the run).

class AnsibleController extends Controller
{
    public function index()
    {
        $inventoryFile = '/etc/ansible/hosts';
        $ansible = new Ansible(
            '/home/vagrant/Sites/goldaccess/resources/assets/ansible-playbook/',
            '/usr/bin/ansible-playbook',
            '/usr/bin/ansible-galaxy'
        );

        $ansibleRunStatus = null;
        $ansibleOutput = null;
        $ansible->playbook()->play('test.yml')->inventoryFile($inventoryFile)->execute(function ($type, $buffer) use (&$ansibleRunStatus, &$ansibleOutput) {
            if (Process::ERR === $type) {
                $ansibleRunStatus = 1;
                // Not currently caputuring output
                // $ansibleOutput = $buffer;
            } else {
                $ansibleRunStatus = 0;
                // Not currently caputuring output
                // $ansibleOutput = $buffer;
            }
        });

        return view('ansible.index');
    }

}

The only thing (which I'm thinking about for a few weeks now) is the synchronicity of the ansible deployment and the request. You're firing the task and then php is waiting for a result - that might cause a lot of waiting time for a user.
My idea was to trigger the deploy e.g. as an ajax request, store the output (and result) in a database and periodically check on the status of the task. That might give you a better user experience, since ansible tends to run up to 2 minutes, given enough complexity of tasks (composer install, gulp runs etc.).
From the implementation point of view it's ok how you're using the lib :-)

Interesting that you bring that up. I thought the wait time might have a pretty big impact on user experience, and that was before you mentioned things like gulp runs. I don't know about you, but my gulp runs take forever.

That said, I kind of just moved on with this test controller because I think/hope that I'll get away with it due to something I'm planning for my application..... I intend to run this inside of a "Job" in laravel. The job is configured to be queued. No idea if this will hide the time it takes to run the ansible playbook, but it should. I know that doesn't help your cause much, but it will be interesting to see how the application behaves when I fire this from within a job.

On a related note, after posting this class, I was playing around and added a flash_message to that index method. I am now wondering how that will behave when it's in a Job. If it is super wonky, I might decide to use pusher or some other websockets based 'thing' to notify the end user when that job has finished. ?? I don't know yet.

I can't wait to see where you go with this project. I would love to contribute any way I can. My background is in system administration with some really dirty use of PHP and shell scripting. I'm catching up on the OOP thing and focusing on Laravel. Just thought I'd warn you in case any of my questions lead to you wondering if this fool knows what the hell he's doing. The answer could very likely be 'no'.

Thanks for the package! I think it's a great addition to the universe!

If you queue that within Laravel, it might work like a cron. Flash message sounds like Symfony and is session-related, so not the best idea to be uset when cronjobbing :-)
And I'm some kind of dev-ops guy, managing system architecture and also infrastructure, so I'm quite familiar with your situation... And thumbs up for your work, always good to deepen the oop know-how and your questions were not stupid - not knowing and being stupid are two completely differen things :-)
And thank your for the praise, really appreaciate that!

Very very good point on the flash_message thing. That's totally a session thing and regardless of the actual outcome, I believe it to be completely inappropriate to put into a laravel "job". I do however think that event broadcasting (pusher/websocket/etc.) would be a pretty clever way to let the job do it's thing and then alert the user. Right now, I'm making changes to the isc-dhcp-server but I can definitely see massive scope creep on the horizon --> and the better this is going, the more true that will be! That will be a great problem to have.

Now I'm off to untangle the (huge) mess I have with hard-coded paths in my ansible playbook in my dev environment. It's reeking havoc when I push to the deployment environment. Tiny, baby steps all the way here. After that, I'll make a proper 'role' out of my deployment script. It's getting big and ugly.

Thanks for your kind words. If there is anything I can help with, testing different scenarios or environments, I'd be happy to. Btw, the more flight time I have with ansible, the more I wish it had been around a long long time ago!!

Everyone started small at some point, so it's completely natural - as long as you see the potential for improvement in your code: You're on the right way :-)

Concerning ansible, have a look at Jeff Geerling's book (https://leanpub.com/ansible-for-devops) and also his github repos (https://github.com/geerlingguy). Really apreciate his work.

Websockets: sounds like a good idea. But then... just trigger the "build" via ajax and token, let the commandline process run and fire back (sockets) when done.