public void TestAzureGetWithoutSlash()
        {
            downloader.Setup(m => m.DownloadPackageToDisk(It.Is<Uri>(u => u.ToString().StartsWith(@"https://test.blob.core.windows.net/container/large.rar")),
                                                          It.Is<bool>(b => b == false),
                                                          It.Is<string>(s => string.Equals(s, @"C:\Temp"))))
                                                          .Returns(@"c:\temp")
                                                          .Verifiable();
            var args = new BootStrapperArgs()
            {
                Get = "container/large.rar",
                LocalResource = @"C:\Temp",
                StorageConnection = this.validConnection
            };

            var manager = new BootStrapperManager(logger.Object, downloader.Object, runner.Object, unzipper.Object);
            manager.Start(args);

            downloader.VerifyAll();
        }
        public void TestAzureGetWithSlash()
        {
            var downloader = new Mock<IPackageDownloader>();
            downloader.Setup(m => m.DownloadPackageToDisk(It.Is<Uri>(u => u.ToString().StartsWith(@"https://test.blob.core.windows.net/container/large.rar")),
                                                          It.Is<bool>(b => b == false),
                                                          It.Is<string>(s => string.Equals(s, @"C:\Temp")))).Verifiable();

            var runner = new Mock<IPackageRunner>();
            var unzipper = new Mock<IPackageUnzipper>();
            var logger = new Mock<ILogger>();

            //Test must be updated to start the Development storage or to replace with a real key or do more mocks work
            var args = new BootStrapperArgs()
            {
                Get = "/container/large.rar",
                LocalResource = @"C:\Temp",
                StorageConnection = @"UseDevelopmentStorage=true"
            };

            var manager = new BootStrapperManager(logger.Object, downloader.Object, runner.Object, unzipper.Object);
            manager.Start(args);

            downloader.VerifyAll();
        }
        internal static void Main(string[] args)
        {
            try
            {
                // Expand first and then bind to Args
                var expanded = args.Select(a => parser.ParseArguments(a)).ToArray();

                var config = Args.Configuration.Configure<CommandArgs>();

                var cmds = config.AsFluent()
                    .UsingStringComparer(StringComparer.InvariantCultureIgnoreCase)
                    .UsingSwitchDelimiter("/")
                    .Initialize()
                    .CreateAndBind(expanded);

                if (args.Length < 1 || args.Length == 1 && cmds.ShowHelp)
                {
                    var help = new HelpProvider();
                    var commandsHelp = help.GenerateModelHelp<CommandArgs>(config);

                    var formatter = new Args.Help.Formatters.ConsoleHelpFormatter();
                    formatter.WriteHelp(commandsHelp, Console.Out);

                    return;
                }

                // TODO: Research for a better way to validate parameters with Args
                try
                {
                    ValidateArgs(cmds);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    Console.WriteLine();
                    Console.WriteLine("Try bootstrapper -help for more information");
                }

                //simple mapping
                var bootArgs = new BootStrapperArgs
                    {
                        Args = cmds.Args,
                        Block = cmds.Block,
                        EnableSystemProfile = cmds.EnableSystemProfile,
                        Get = cmds.Get,
                        LocalResource = cmds.LocalResource,
                        Overwrite = cmds.Overwrite,
                        Put = cmds.Put,
                        Run = cmds.Run,
                        RunAlways = cmds.RunAlways,
                        StorageConnection = cmds.StorageConnection,
                        Unzip = !String.IsNullOrWhiteSpace(cmds.Unzip),
                        UnzipTarget = cmds.Unzip
                    };

                //default to trace logger
                var logger = new TraceLogger();
                var manager = new BootStrapperManager(logger, new PackageDownloader(logger), new PackageRunner(logger),
                                                      new PackageUnzipper(logger), new PackageUploader(logger),
                                                      new PackageZipper(logger));

                manager.Start(bootArgs);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());

                // TODO: Push error to blob storage?
            }
        }
        public void TestUnzip()
        {
            var downloader = new Mock<IPackageDownloader>();
            downloader.Setup(m => m.DownloadPackageToDisk(It.IsAny<Uri>(), It.IsAny<bool>(), It.IsAny<string>())).Returns(@"C:\Temp\testing.zip").Verifiable();

            var runner = new Mock<IPackageRunner>();
            var unzipper = new Mock<IPackageUnzipper>();
            var logger = new Mock<ILogger>();

            unzipper.Setup(m => m.Unzip(It.Is<string>(s => string.Equals(s, @"C:\Temp\testing.zip")), It.Is<string>(s => s == @"C:\Temp"), It.Is<bool>(b => b == false))).Verifiable();

            var args = new BootStrapperArgs()
            {
                Get = "http://contoso.net/downloads/testing.zip",
                LocalResource = @"C:\Temp", // when run on bootstrapper.exe, this is assiged to whatever unziptarget is
                UnzipTarget = @"C:\Temp",
                Unzip = true
            };

            var manager = new BootStrapperManager(logger.Object, downloader.Object, runner.Object, unzipper.Object);
            manager.Start(args);

            unzipper.VerifyAll();
        }
        public void TestSimpleGet()
        {
            var uri = new Uri(@"http://contoso.com/installer.msi");

            var downloader = new Mock<IPackageDownloader>();
            downloader.Setup(m => m.DownloadPackageToDisk(It.Is<Uri>(u => u.Equals(uri)),
                                                          It.Is<bool>(b => b == false),
                                                          It.Is<string>(s => string.Equals(s, @"C:\Temp")))).Verifiable();

            var runner = new Mock<IPackageRunner>();
            var unzipper = new Mock<IPackageUnzipper>();
            var logger = new Mock<ILogger>();

            var args = new BootStrapperArgs()
            {
                Get = uri.ToString(),
                LocalResource = @"C:\Temp"
            };

            var manager = new BootStrapperManager(logger.Object, downloader.Object, runner.Object, unzipper.Object);
            manager.Start(args);

            downloader.VerifyAll();
        }
        public void TestSimpleGet()
        {
            var uri = new Uri(@"http://contoso.com/installer.msi");

            downloader.Setup(m => m.DownloadPackageToDisk(uri, false, @"C:\Temp"))
                      .Returns(@"c:\temp");

            var args = new BootStrapperArgs()
            {
                Get = uri.ToString(),
                LocalResource = @"C:\Temp"
            };

            var manager = new BootStrapperManager(logger.Object, downloader.Object, runner.Object, unzipper.Object);
            manager.Start(args);

            downloader.VerifyAll();
        }
        /// <summary>
        /// Begins orchestration of bootstrapper tasks.
        /// </summary>
        /// <param name="args">The validated args parsed from the commmand line.</param>
        public void Start(BootStrapperArgs args)
        {
            try
            {
                Client = String.IsNullOrEmpty(args.StorageConnection) ? null : CloudStorageAccount.Parse(args.StorageConnection).CreateCloudBlobClient();
            }
            catch (Exception ex)
            {
                throw new ArgumentException("The Azure storage connection string is not valid:  " + ex.Message, args.StorageConnection);
            }

            //download package (if not previously downloaded).  RunAlways forces download always.
            Uri targetUri = null;
            String package = null;
            if ( !String.IsNullOrEmpty(args.Get) )
            {
                Uri urlToDownload = null;

                //if a storage account is present generate a SAS for the get
                if (Client != null)
                {
                    //x| var account = CloudStorageAccount.Parse(args.StorageConnection);
                    //x| var client = account.CreateCloudBlobClient();

                    var reference = Client.GetBlobReferenceFromServer(new Uri(args.Get.StartsWith("/") ? args.Get.Substring(1) : args.Get));
                    var sas = reference.GetSharedAccessSignature(
                        new SharedAccessBlobPolicy()
                        {
                            Permissions = SharedAccessBlobPermissions.Read,
                            SharedAccessExpiryTime = DateTime.Now.AddMinutes(10)
                        });

                    urlToDownload = new Uri(reference.Uri, sas);
                }
                else //otherwise, this is a standard get
                {
                    if (!Uri.TryCreate(args.Get, UriKind.Absolute, out urlToDownload))
                        throw new ArgumentException("Invalid Uri", "args.Get");
                }

                //always download as a get
                package = this.downloader.DownloadPackageToDisk(
                    urlToDownload,
                    args.RunAlways,
                    args.LocalResource
                    );

                //Unzip without replace.  RunAlways forces unzip with replace
                if (args.Unzip)
                {
                    this.unzipper.Unzip(package, args.UnzipTarget, args.RunAlways);
                }
            }

            if ( !String.IsNullOrEmpty(args.Put) )
            {
                if (Client != null)
                {
                    try {
                        ICloudBlob blob = Client.GetBlobReferenceFromServer(new Uri(args.Put.Trim('/')));
                        //blob.Container.CreateIfNotExist();
                        blob.Container.CreateIfNotExists(requestOptions: null, operationContext: null);
                        String target = blob.GetSharedAccessSignature(
                            new SharedAccessBlobPolicy
                            {
                                Permissions = SharedAccessBlobPermissions.Write,
                                SharedAccessExpiryTime = DateTime.Now.AddMinutes(30)
                            });
                        if (args.Overwrite)
                            blob.DeleteIfExists();
                        targetUri = new Uri(blob.Uri, target);
                    }
                    catch ( StorageException ex ) {
                        if (Uri.IsWellFormedUriString(args.Put, UriKind.Relative))
                            throw new ArgumentException(
                                "A valid connection string to Azure blob storage must be supplied when uploading to a relative URL.\n" + ex.Message,
                                args.StorageConnection);
                    }
                }
                if ( targetUri == null ) //i| fall back on standard put.
                {
                    if ( !Uri.TryCreate(args.Put, UriKind.Absolute, out targetUri) )
                        throw new ArgumentException("Invalid URL was supplied for the PUT argument.", args.Put);
                }

                //i| Only package when we don't have a filename (didn't get), and the local resource is an existing folder.
                if ( package == null &&  Directory.Exists(args.LocalResource))
                {
                    package = Path.Combine(args.LocalResource, Path.GetFileName(targetUri.LocalPath));
                    this.zipper.Zip(args.LocalResource, package, args.Overwrite);
                }

                //i| Always download as a get
                package = this.uploader.UploadPackageToStorage(
                    package ?? args.LocalResource,
                    targetUri,
                    args.Overwrite
                    );
            }

            //Run the command, record output to local disk for repository
            if (!String.IsNullOrEmpty(args.Run))
            {
                if (!this.runner.PackageExists(args.Run) || args.RunAlways)
                {
                    this.runner.Start(
                        args.Run,
                        args.Args,
                        args.EnableSystemProfile,
                        args.Block
                        );
                }
            }
        }