private void SaveTagInfoToImageInfoFile(DateTime createdDate, ImageArtifactDetails imageArtifactDetails) { _loggerService.WriteSubheading("SETTING TAG INFO"); IEnumerable <ImageData> images = imageArtifactDetails.Repos .SelectMany(repo => repo.Images) .Where(image => image.Manifest != null); Parallel.ForEach(images, image => { image.Manifest.Created = createdDate; TagInfo sharedTag = image.ManifestImage.SharedTags.First(); image.Manifest.Digest = DockerHelper.GetDigestString( image.ManifestRepo.FullModelName, _manifestToolService.GetManifestDigestSha( ManifestMediaType.ManifestList, sharedTag.FullyQualifiedName, Options.IsDryRun)); }); string imageInfoString = JsonHelper.SerializeObject(imageArtifactDetails); File.WriteAllText(Options.ImageInfoPath, imageInfoString); }
private IEnumerable <string> GenerateManifests(RepoInfo repo, ImageInfo image) { yield return(GenerateManifest(repo, image, image.SharedTags.Select(tag => tag.Name), tag => DockerHelper.GetImageName(Manifest.Registry, Options.RepoPrefix + repo.Name, tag), platform => platform.Tags.First())); IEnumerable <IGrouping <string, TagInfo> > syndicatedTagGroups = image.SharedTags .Where(tag => tag.SyndicatedRepo != null) .GroupBy(tag => tag.SyndicatedRepo); foreach (IGrouping <string, TagInfo> syndicatedTags in syndicatedTagGroups) { string syndicatedRepo = syndicatedTags.Key; IEnumerable <string> destinationTags = syndicatedTags.SelectMany(tag => tag.SyndicatedDestinationTags); // There won't always be a platform tag that's syndicated. So if a manifest tag is syndicated, we need to account // for the possibility that a given platform for that manifest will not have a matching syndicated repo. yield return(GenerateManifest(repo, image, destinationTags, tag => DockerHelper.GetImageName(Manifest.Registry, Options.RepoPrefix + syndicatedRepo, tag), platform => platform.Tags.FirstOrDefault(tag => tag.SyndicatedRepo == syndicatedRepo))); } }
private void EnsureArchitectureMatches(PlatformInfo platform, IEnumerable <string> allTags) { if (platform.Model.Architecture == _dockerService.Architecture) { return; } string primaryTag = allTags.First(); IEnumerable <string> secondaryTags = allTags.Except(new[] { primaryTag }); // Get the architecture from the built image's metadata string actualArchitecture = DockerHelper.GetImageArch(primaryTag, Options.IsDryRun); string expectedArchitecture = platform.Model.Architecture.GetDockerName(); // If the architecture of the built image is what we expect, then exit the method; otherwise, continue // with updating the architecture metadata. if (string.Equals(actualArchitecture, expectedArchitecture)) { return; } // Save the Docker image to a tar file string tempImageTar = "image.tar.gz"; DockerHelper.SaveImage(primaryTag, tempImageTar, Options.IsDryRun); try { string tarContentsDirectory = "tar_contents"; Directory.CreateDirectory(tarContentsDirectory); try { // Extract the tar file to a separate directory ExecuteHelper.Execute("tar", $"-xf {tempImageTar} -C {tarContentsDirectory}", Options.IsDryRun); // Open the manifest to find the name of the Config json file string manifestContents = File.ReadAllText(Path.Combine(tarContentsDirectory, "manifest.json")); JArray manifestDoc = JArray.Parse(manifestContents); if (manifestDoc.Count != 1) { throw new InvalidOperationException( $"Only expected one element in tar archive's manifest:{Environment.NewLine}{manifestContents}"); } // Open the Config json file and set the architecture value string configPath = Path.Combine(tarContentsDirectory, manifestDoc[0]["Config"].Value <string>()); string configContents = File.ReadAllText(configPath); JObject config = JObject.Parse(configContents); config["architecture"] = expectedArchitecture; // Overwrite the Config json file with the updated architecture value configContents = JsonConvert.SerializeObject(config); File.WriteAllText(configPath, configContents); // Repackage the directory into an updated tar file ExecuteHelper.Execute("tar", $"-cf {tempImageTar} -C {tarContentsDirectory} .", Options.IsDryRun); } finally { Directory.Delete(tarContentsDirectory, recursive: true); } // Load the updated tar file back into Docker DockerHelper.LoadImage(tempImageTar, Options.IsDryRun); } finally { File.Delete(tempImageTar); } // Recreate the other tags so that they get the updated architecture value. Parallel.ForEach(secondaryTags, tag => { _dockerService.CreateTag(primaryTag, tag, Options.IsDryRun); }); }
private void SetPlatformDataDigest(PlatformData platform, string tag) { // The digest of an image that is pushed to ACR is guaranteed to be the same when transferred to MCR. string digest = _imageDigestCache.GetImageDigest(tag, Options.IsDryRun); if (digest != null) { digest = DockerHelper.GetDigestString(platform.PlatformInfo.FullRepoModelName, DockerHelper.GetDigestSha(digest)); } if (platform.Digest != null && platform.Digest != digest) { // Pushing the same image with different tags should result in the same digest being output throw new InvalidOperationException( $"Tag '{tag}' was pushed with a resulting digest value that differs from the corresponding image's digest value." + Environment.NewLine + $"\tDigest value from image info: {platform.Digest}{Environment.NewLine}" + $"\tDigest value retrieved from query: {digest}"); } platform.Digest = digest; }
private void RefreshContainersListInternal() { int totalContainers = 0; try { IContainerViewModel selectedContainer = SelectedContainerInstance; SelectedContainerInstance = null; IEnumerable <DockerContainerInstance> containers; if (SelectedConnection is LocalConnectionViewModel) { containers = DockerHelper.GetLocalDockerContainers(Hostname, out totalContainers); } else { ContainersFoundText = UIResources.SSHConnectingStatusText; var connection = SelectedConnection.Connection; if (connection == null) { UpdateStatusMessage(UIResources.SSHConnectionFailedStatusText, isError: true); return; } containers = DockerHelper.GetRemoteDockerContainers(connection, Hostname, out totalContainers); } if (containers.Count() > 0) { string serverOS; if (DockerHelper.TryGetServerOS(Hostname, out serverOS)) { bool lcow; bool getLCOW = DockerHelper.TryGetLCOW(Hostname, out lcow); TextInfo textInfo = new CultureInfo("en-US", false).TextInfo; serverOS = textInfo.ToTitleCase(serverOS); /* Note: LCOW is the abbreviation for Linux Containers on Windows * * In LCOW, both Linux and Windows containers can run simultaneously in a Docker (Windows) Engine. * Thus, the container platform must be queried directly. * Otherwise, the container platform must match that of the server engine. */ if (lcow && serverOS.Contains("Windows")) { foreach (DockerContainerInstance container in containers) { string containerPlatform = string.Empty; if (DockerHelper.TryGetContainerPlatform(Hostname, container.Name, out containerPlatform)) { container.Platform = textInfo.ToTitleCase(containerPlatform); } else { container.Platform = unknownOS; } } } else { foreach (DockerContainerInstance container in containers) { container.Platform = serverOS; } } } else { foreach (DockerContainerInstance container in containers) { container.Platform = unknownOS; } } } ContainerInstances = new ObservableCollection <IContainerViewModel>(containers.Select(item => new DockerContainerViewModel(item)).ToList()); OnPropertyChanged(nameof(ContainerInstances)); if (ContainerInstances.Count() > 0) { if (selectedContainer != null) { var found = ContainerInstances.FirstOrDefault(c => selectedContainer.Equals(c)); if (found != null) { SelectedContainerInstance = found; return; } } SelectedContainerInstance = ContainerInstances[0]; } } catch (Exception ex) { UpdateStatusMessage(UIResources.ErrorStatusTextFormat.FormatCurrentCultureWithArgs(ex.Message), isError: true); return; } finally { if (ContainerInstances.Count() > 0) { if (ContainerInstances.Count() < totalContainers) { UpdateStatusMessage(UIResources.ContainersNotAllParsedStatusText.FormatCurrentCultureWithArgs(totalContainers - ContainerInstances.Count()), isError: false); ContainersFoundText = UIResources.ContainersNotAllParsedText.FormatCurrentCultureWithArgs(ContainerInstances.Count(), totalContainers); } else { ContainersFoundText = UIResources.ContainersFoundStatusText.FormatCurrentCultureWithArgs(ContainerInstances.Count()); } } else { ContainersFoundText = UIResources.NoContainersFound; } IsRefreshEnabled = true; } }
private List <string> GetPathsToRebuild( IEnumerable <PlatformInfo> allPlatforms, PlatformInfo platform, RepoData repoData) { bool foundImageInfo = false; List <string> pathsToRebuild = new List <string>(); void processPlatformWithMissingImageInfo(PlatformInfo platform) { _loggerService.WriteMessage( $"WARNING: Image info not found for '{platform.DockerfilePath}'. Adding path to build to be queued anyway."); IEnumerable <PlatformInfo> dependentPlatforms = platform.GetDependencyGraph(allPlatforms); pathsToRebuild.AddRange(dependentPlatforms.Select(p => p.Model.Dockerfile)); } if (repoData == null || repoData.Images == null) { processPlatformWithMissingImageInfo(platform); return(pathsToRebuild); } foreach (ImageData imageData in repoData.Images) { PlatformData platformData = imageData.Platforms .FirstOrDefault(platformData => platformData.PlatformInfo == platform); if (platformData != null) { foundImageInfo = true; string fromImage = platform.FinalStageFromImage; string currentDigest; currentDigest = LockHelper.DoubleCheckedLockLookup(_imageDigestsLock, _imageDigests, fromImage, () => { string digest = _manifestToolService.GetManifestDigestSha(ManifestMediaType.Any, fromImage, Options.IsDryRun); return(DockerHelper.GetDigestString(DockerHelper.GetRepo(fromImage), digest)); }); bool rebuildImage = platformData.BaseImageDigest != currentDigest; _loggerService.WriteMessage( $"Checking base image '{fromImage}' from '{platform.DockerfilePath}'{Environment.NewLine}" + $"\tLast build digest: {platformData.BaseImageDigest}{Environment.NewLine}" + $"\tCurrent digest: {currentDigest}{Environment.NewLine}" + $"\tImage is up-to-date: {!rebuildImage}{Environment.NewLine}"); if (rebuildImage) { IEnumerable <PlatformInfo> dependentPlatforms = platform.GetDependencyGraph(allPlatforms); pathsToRebuild.AddRange(dependentPlatforms.Select(p => p.Model.Dockerfile)); } break; } } if (!foundImageInfo) { processPlatformWithMissingImageInfo(platform); } return(pathsToRebuild); }
protected void ExecuteWithUser(Action action) { DockerHelper.ExecuteWithUser(action, Options.Username, Options.Password, Manifest.Registry, Options.IsDryRun); }
internal void RefreshContainersList() { IsRefreshEnabled = false; try { IContainerViewModel selectedContainer = SelectedContainerInstance; SelectedContainerInstance = null; ContainersFoundText = UIResources.SearchingStatusText; // Clear everything ContainerInstances?.Clear(); UpdateStatusMessage(string.Empty, false); IEnumerable <DockerContainerInstance> containers; if (SelectedConnection is LocalConnectionViewModel) { containers = DockerHelper.GetLocalDockerContainers(Hostname); } else { ContainersFoundText = UIResources.SSHConnectingStatusText; var connection = SelectedConnection.Connection; if (connection == null) { UpdateStatusMessage(UIResources.SSHConnectionFailedStatusText, isError: true); return; } containers = DockerHelper.GetRemoteDockerContainers(connection, Hostname); } ContainerInstances = new ObservableCollection <IContainerViewModel>(containers.Select(item => new DockerContainerViewModel(item)).ToList()); OnPropertyChanged(nameof(ContainerInstances)); if (ContainerInstances.Count() > 0) { if (selectedContainer != null) { var found = ContainerInstances.FirstOrDefault(c => selectedContainer.Equals(c)); if (found != null) { SelectedContainerInstance = found; return; } } SelectedContainerInstance = ContainerInstances[0]; } } catch (Exception ex) { UpdateStatusMessage(UIResources.ErrorStatusTextFormat.FormatCurrentCultureWithArgs(ex.Message), isError: true); return; } finally { if (ContainerInstances.Count() > 0) { ContainersFoundText = UIResources.ContainersFoundStatusText.FormatCurrentCultureWithArgs(ContainerInstances.Count()); } else { ContainersFoundText = UIResources.NoContainersFound; } IsRefreshEnabled = true; } }
private string GenerateManifest(RepoInfo repo, ImageInfo image, IEnumerable <string> tags, Func <string, string> getImageName, Func <PlatformInfo, TagInfo?> getTagRepresentative) { string imageName = getImageName(tags.First()); StringBuilder manifestYml = new(); manifestYml.AppendLine($"image: {imageName}"); _publishedManifestTags.Add(imageName); string repoName = DockerHelper.GetRepo(imageName); IEnumerable <string> additionalTags = tags.Skip(1); if (additionalTags.Any()) { manifestYml.AppendLine($"tags: [{string.Join(",", additionalTags)}]"); } _publishedManifestTags.AddRange(additionalTags.Select(tag => $"{repoName}:{tag}")); manifestYml.AppendLine("manifests:"); foreach (PlatformInfo platform in image.AllPlatforms) { TagInfo?imageTag; if (platform.Tags.Any()) { imageTag = getTagRepresentative(platform); } else { (ImageInfo Image, PlatformInfo Platform)matchingImagePlatform = repo.AllImages .SelectMany(image => image.AllPlatforms .Select(p => (Image: image, Platform: p)) .Where(imagePlatform => platform != imagePlatform.Platform && PlatformInfo.AreMatchingPlatforms(image, platform, imagePlatform.Image, imagePlatform.Platform) && imagePlatform.Platform.Tags.Any())) .FirstOrDefault(); if (matchingImagePlatform.Platform is null) { throw new InvalidOperationException( $"Could not find a platform with concrete tags for '{platform.DockerfilePathRelativeToManifest}'."); } imageTag = getTagRepresentative(matchingImagePlatform.Platform); } if (imageTag is not null) { manifestYml.AppendLine($"- image: {getImageName(imageTag.Name)}"); manifestYml.AppendLine($" platform:"); manifestYml.AppendLine($" architecture: {platform.Model.Architecture.GetDockerName()}"); manifestYml.AppendLine($" os: {platform.Model.OS.GetDockerName()}"); if (platform.Model.Variant != null) { manifestYml.AppendLine($" variant: {platform.Model.Variant}"); } } } return(manifestYml.ToString()); }
public MosquittoVerifier(CLIContext context) { Docker = new DockerHelper(context); Context = context; }
private string GenerateTagsListing(RepoInfo repo, string tagsMetadata) { Logger.WriteSubheading("GENERATING TAGS LISTING"); string tagsDoc; string tempDir = $"{Options.GetCommandName()}-{DateTime.Now.ToFileTime()}"; Directory.CreateDirectory(tempDir); try { string tagsMetadataFileName = Path.GetFileName(repo.Model.McrTagsMetadataTemplate); File.WriteAllText( Path.Combine(tempDir, tagsMetadataFileName), tagsMetadata); string dockerfilePath = Path.Combine(tempDir, "Dockerfile"); File.WriteAllText( dockerfilePath, $"FROM {McrTagsRenderingToolTag}{Environment.NewLine}COPY {tagsMetadataFileName} /tableapp/files/ "); string renderingToolId = $"renderingtool-{DateTime.Now.ToFileTime()}"; DockerHelper.PullImage(McrTagsRenderingToolTag, Options.IsDryRun); ExecuteHelper.Execute( "docker", $"build -t {renderingToolId} -f {dockerfilePath} {tempDir}", Options.IsDryRun); try { ExecuteHelper.Execute( "docker", $"run --name {renderingToolId} {renderingToolId} {tagsMetadataFileName}", Options.IsDryRun); try { string outputPath = Path.Combine(tempDir, "output.md"); ExecuteHelper.Execute( "docker", $"cp {renderingToolId}:/tableapp/files/{repo.Name.Replace('/', '-')}.md {outputPath}", Options.IsDryRun ); tagsDoc = File.ReadAllText(outputPath); } finally { ExecuteHelper.Execute("docker", $"container rm -f {renderingToolId}", Options.IsDryRun); } } finally { ExecuteHelper.Execute("docker", $"image rm -f {renderingToolId}", Options.IsDryRun); } } finally { Directory.Delete(tempDir, true); } if (Options.IsVerbose) { Logger.WriteSubheading($"Tags Documentation:"); Logger.WriteMessage(tagsDoc); } return(tagsDoc); }
public static int Main(string[] args) { var app = new CommandLineApplication { Name = "EOSCPPManager", Description = "A EOS Smart Contract helper tool", }; app.ThrowOnUnexpectedArgument = false; app.HelpOption(inherited: true); app.Command("util", configCmd => { configCmd.OnExecute(() => { //Console.WriteLine("Specify a subcommand"); configCmd.ShowHelp(); return(1); }); configCmd.Command("cleanDocker", setCmd => { setCmd.Description = "Remove unused Docker containers that have been used to compile"; setCmd.OnExecute(() => { logger.Info($"Start cleanup"); try { var x = DockerHelper.dockerCleanup().Result; } catch (Exception ex) { logger.Error(ex.Message); } }); }); }); app.Command("init", configCmd => { configCmd.OnExecute(() => { //Console.WriteLine("Specify a subcommand"); configCmd.ShowHelp(); return(1); }); configCmd.Command("docker", setCmd => { setCmd.Description = "Check that the required docker images exist on the machine and download any missing"; setCmd.OnExecute(() => { IConfiguration config = new ConfigurationBuilder() .AddJsonFile("appsettings.json", true, true) .Build(); var eosiocppDockerImage = config["eosiocppDockerImage"]; logger.Info("Check connection to local docker instance and confirm that image \"{0}\" exists", eosiocppDockerImage); logger.Info("If this step hange/freezes for an extended period of time please confirm the following:"); logger.Info("\t 1. That your docker settings have \"expose daemon\" enabled. On windows this is tcp://localhost:2375 by default."); logger.Info("\t 2. That your Antivirus is not blocking access to tcp://localhost:2375"); var exists = DockerHelper.CheckImageExistsAsync(eosiocppDockerImage).Result; if (!exists) { var y = DockerHelper.getImageAsync(eosiocppDockerImage).Result; } else { logger.Info("Connection = good. Image exists. You're good to go."); } //logger.Info(list); }); }); configCmd.Command("windows", setCmd => { setCmd.Description = "Initialize windows PATH variable - Must be run as Administartor"; setCmd.OnExecute(() => { logger.Info($"Start Initialize windows env"); //if(DirectoryExistsAttribute.e) var lib = new EOSCPPManagerCore(); try { lib.initializeWindowEnv(); } catch (Exception ex) { logger.Error(ex.Message); } }); }); configCmd.Command("include", setCmd => { setCmd.Description = "Copy header files and other include files."; setCmd.OnExecute(() => { logger.Info($"Start Initialize include"); //if(DirectoryExistsAttribute.e) var lib = new EOSCPPManagerCore(); try { lib.initializeInclude(); } catch (Exception ex) { logger.Error(ex.Message); } }); }); }); app.Command("template", configCmd => { configCmd.OnExecute(() => { //Console.WriteLine("Specify a subcommand"); configCmd.ShowHelp(); return(1); }); configCmd.Command("new", setCmd => { setCmd.Description = "Create a new smart contract template"; var pathOption = setCmd.Option("-p|--path <PATH>", "The path to the parent folder, which will contain the new template", CommandOptionType.SingleValue).IsRequired(); var nameOption = setCmd.Option("-n|--name <NAME>", "The path to the parent folder, which will contain the new template", CommandOptionType.SingleValue).IsRequired(); var overwriteOption = setCmd.Option("-o|--overwrite", "If a project exists, delete and create new", CommandOptionType.NoValue); setCmd.OnExecute(() => { String path = pathOption.Value(); String name = nameOption.Value(); bool overwrite = false; if (overwriteOption.Values.Count > 0) { overwrite = true; } //Console.WriteLine($"Create new project in {path}"); logger.Info($"Begin create of new smart contract {name} in parent folder {path}"); //if(DirectoryExistsAttribute.e) var lib = new EOSCPPManagerCore(); try { lib.createNewSmartContract(path, name, overwrite); } catch (Exception ex) { logger.Error(ex.Message); } }); }); }); app.Command("build", configCmd => { var eosiocppDockerImage = config["eosiocppDockerImage"]; var pathOption = configCmd.Option("-p|--path <PATH>", "The path to the parent folder, which will contain the new template (*Required)", CommandOptionType.SingleValue).IsRequired(); var dockerImageOption = configCmd.Option("-d|--dockerImage <ImageName>", string.Format("The name of the docker image to use (Default: {0})", eosiocppDockerImage), CommandOptionType.SingleValue); var watchOption = configCmd.Option("-w|--watch", "Continue watching this folder for changes (*Currently Required)", CommandOptionType.NoValue); configCmd.OnExecute(() => { var path = pathOption.Value(); //var dockerImage = "binaryfocus/eosio_wasm_1.2.6"; var dockerImage = eosiocppDockerImage; var watch = false; if (dockerImageOption.Values.Count > 0) { dockerImage = dockerImageOption.Value(); } if (watchOption.Values.Count > 0) { watch = true; } if (watch) { Console.WriteLine("Begin watching {0}. Build using docker image {1}.", path, dockerImage, watch); } else { Console.WriteLine("Compile {0} using docker image {1}. Continue watching = {2}", path, dockerImage, watch); } //logger.Info("Begin watching '{0}'", parsedWatchArgs.Path); Watcher.start(path, dockerImage); //It doesn't matter what file name we push onto the list, as long as it's a cpp or hpp it'll trigger a build. DockerHelper.init(path, dockerImage, watch); Watcher.addToQueue("test.cpp"); if (watch) { while (1 < 2) { Thread.Sleep(500); // Every 500ms we chech the build queue and trigger a build in the Docker container. // The purpose of the queue is to make sure that we don't end up with multiple builds in parallel. Watcher.checkQueue(); } } else { //logger.Info("We're still experiencing some problems with the one off build command and docker. Please use the --watch option to watch the folder instead."); Watcher.checkQueue(); } //configCmd.ShowHelp(); return(1); }); }); app.OnExecute(() => { Console.WriteLine("Specify a subcommand"); app.ShowHelp(); return(1); }); int result = -1; try { result = app.Execute(args); } catch (Exception ex) { app.ShowHelp(); } return(result); }
protected Task ExecuteWithUserAsync(Func <Task> action) { Options.CredentialsOptions.Credentials.TryGetValue(Manifest.Registry ?? "", out RegistryCredentials? credentials); return(DockerHelper.ExecuteWithUserAsync(action, credentials?.Username, credentials?.Password, Manifest.Registry, Options.IsDryRun)); }
protected void ExecuteWithUser(Action action) { DockerHelper.ExecuteWithUser(action, Options.Username, Options.Password, Options.Server, Options.IsDryRun); }