new feature: capture and forward stdin to types

Signed-off-by: Steven Armstrong <steven@icarus.ethz.ch>
This commit is contained in:
Steven Armstrong 2012-06-04 14:11:34 +02:00
parent f087057c98
commit 06649d3478
6 changed files with 80 additions and 2 deletions

View file

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# 2011-2012 Nico Schottelius (nico-cdist at schottelius.org) # 2011-2012 Nico Schottelius (nico-cdist at schottelius.org)
# 2012 Steven Armstrong (steven-cdist at armstrong.cc)
# #
# This file is part of cdist. # This file is part of cdist.
# #
@ -22,6 +23,7 @@
import argparse import argparse
import logging import logging
import os import os
import sys
import cdist import cdist
from cdist import core from cdist import core
@ -67,6 +69,7 @@ class Emulator(object):
self.commandline() self.commandline()
self.setup_object() self.setup_object()
self.save_stdin()
self.record_requirements() self.record_requirements()
self.record_auto_requirements() self.record_auto_requirements()
self.log.debug("Finished %s %s" % (self.cdist_object.path, self.parameters)) self.log.debug("Finished %s %s" % (self.cdist_object.path, self.parameters))
@ -137,6 +140,27 @@ class Emulator(object):
# Record / Append source # Record / Append source
self.cdist_object.source.append(self.object_source) self.cdist_object.source.append(self.object_source)
chunk_size = 8192
def _read_stdin(self):
return sys.stdin.buffer.read(self.chunk_size)
def save_stdin(self):
"""If something is written to stdin, save it in the object as
$__object/stdin so it can be accessed in manifest and gencode-*
scripts.
"""
if not sys.stdin.isatty():
try:
# go directly to file instead of using CdistObject's api
# as that does not support streaming
path = os.path.join(self.cdist_object.absolute_path, 'stdin')
with open(path, 'wb') as fd:
chunk = self._read_stdin()
while chunk:
fd.write(chunk)
chunk = self._read_stdin()
except EnvironmentError as e:
raise cdist.Error('Failed to read from stdin: %s' % e)
def record_requirements(self): def record_requirements(self):
"""record requirements""" """record requirements"""

View file

@ -21,12 +21,17 @@
import os import os
import shutil import shutil
import string
import filecmp
import random
import cdist import cdist
from cdist import test from cdist import test
from cdist.exec import local from cdist.exec import local
from cdist import emulator from cdist import emulator
from cdist import core from cdist import core
from cdist import config
import cdist.context
local_base_path = test.cdist_base_path local_base_path = test.cdist_base_path
@ -114,8 +119,7 @@ class AutoRequireEmulatorTestCase(test.CdistTestCase):
self.manifest = core.Manifest(self.target_host, self.local) self.manifest = core.Manifest(self.target_host, self.local)
def tearDown(self): def tearDown(self):
pass shutil.rmtree(self.temp_dir)
#shutil.rmtree(self.temp_dir)
def test_autorequire(self): def test_autorequire(self):
initial_manifest = os.path.join(self.local.manifest_path, "init") initial_manifest = os.path.join(self.local.manifest_path, "init")
@ -216,3 +220,47 @@ class ArgumentsTestCase(test.CdistTestCase):
self.assertTrue('optional1' in cdist_object.parameters) self.assertTrue('optional1' in cdist_object.parameters)
self.assertFalse('optional2' in cdist_object.parameters) self.assertFalse('optional2' in cdist_object.parameters)
self.assertEqual(cdist_object.parameters['optional1'], value) self.assertEqual(cdist_object.parameters['optional1'], value)
class StdinTestCase(test.CdistTestCase):
def setUp(self):
self.orig_environ = os.environ
os.environ = os.environ.copy()
self.target_host = 'localhost'
self.temp_dir = self.mkdtemp()
os.environ['__cdist_out_dir'] = self.temp_dir
local_base_path = fixtures
self.context = cdist.context.Context(
target_host=self.target_host,
remote_copy='scp -o User=root -q',
remote_exec='ssh -o User=root -q',
base_path=local_base_path,
exec_path=test.cdist_exec_path,
debug=False)
self.config = config.Config(self.context)
def tearDown(self):
os.environ = self.orig_environ
shutil.rmtree(self.temp_dir)
def test_file_from_stdin(self):
handle, destination = self.mkstemp(dir=self.temp_dir)
os.close(handle)
source_handle, source = self.mkstemp(dir=self.temp_dir)
candidates = string.ascii_letters+string.digits
with os.fdopen(source_handle, 'w') as fd:
for x in range(100):
fd.write(''.join(random.sample(candidates, len(candidates))))
handle, initial_manifest = self.mkstemp(dir=self.temp_dir)
with os.fdopen(handle, 'w') as fd:
fd.write('__file_from_stdin %s --source %s\n' % (destination, source))
self.context.initial_manifest = initial_manifest
self.config.stage_prepare()
cdist_type = core.CdistType(self.config.local.type_path, '__file')
cdist_object = core.CdistObject(cdist_type, self.config.local.object_path, destination)
# Test weither stdin has been stored correctly
self.assertTrue(filecmp.cmp(source, os.path.join(cdist_object.absolute_path, 'stdin')))

View file

@ -0,0 +1 @@
../../../../../../../conf/type/__file

View file

@ -0,0 +1,4 @@
#!/bin/sh
source="$(cat "$__object/parameter/source")"
cat "$source" | __file "/$__object_id" --source /dev/null