Skip to content

Commit

Permalink
Support to generating the package for docker (#53)
Browse files Browse the repository at this point in the history
* Support to generating the package for docker
  • Loading branch information
sjuarezgx authored May 18, 2022
1 parent 8282e6c commit a654a0c
Show file tree
Hide file tree
Showing 3 changed files with 305 additions and 273 deletions.
6 changes: 6 additions & 0 deletions src/Docker/Definition.target
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
<DeploymentTarget>
<Id>DOCKER</Id>
<Name>Docker Image</Name>
<DeploymentScopes>
<Scope Id = "Backend" />
<Scope Id = "BackendToCloud" />
</DeploymentScopes>
<Version>1.0</Version>
<Description>DeployTo</Description>
<PackageTargets>docker.targets</PackageTargets>
<PackageMsbuild>createpackage.msbuild</PackageMsbuild>
<PackageMsbuildTarget>CreatePackage</PackageMsbuildTarget>
<DeployMsbuild>deploy.msbuild</DeployMsbuild>
<DeployMsbuildTarget>Deploy</DeployMsbuildTarget>
<ResolverFactory>Genexus.Deployment.DockerResolvers.ResolverFactory</ResolverFactory>
Expand Down
283 changes: 283 additions & 0 deletions src/Docker/createpackage.msbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="CreatePackage" ToolsVersion="4.0">
<PropertyGroup>
<GXDeployFileProject>$([System.IO.Path]::GetFullPath('$(DeployFullPath)\..\..\..\..\web\$(ProjectName).gxdproj'))</GXDeployFileProject>
<MainPrefix>a</MainPrefix>
</PropertyGroup>
<Import Project="$(GX_PROGRAM_DIR)\GeneXus.Docker.targets"/>
<Import Project="$(WebSourcePath)\$(DeploymentUnit).props" Condition="Exists('$(WebSourcePath)\$(DeploymentUnit).props')"/>
<Import Project="$(GXDeployFileProject)" Condition ="Exists('$(GXDeployFileProject)')" />
<Import Project="$(GX_PROGRAM_DIR)\Imports.targets" Condition ="!Exists('$(GXDeployFileProject)')"/>

<Target Name="CreateDockerfile">
<GetDockerConfigDefaults Condition="'$(DOCKER_WEBAPPLOCATION)' == '' OR '$(DOCKER_BASE_IMAGE)' == ''"
BuildEnvironment = "$(BuildEnvironment)"
Generator = "$(GENERATOR)"
IsCMD = "$(IsCMD)" >
<Output TaskParameter="WebAppLocation"
PropertyName="DOCKER_WEBAPPLOCATION" />
<Output TaskParameter="BaseImage"
PropertyName="DOCKER_BASE_IMAGE" />
</GetDockerConfigDefaults>

<ItemGroup>
<SourceFile Include="$(DeploySource)" />
</ItemGroup>

<Error Text="Property 'Image App location' cannot be empty" Condition="'$(DOCKER_WEBAPPLOCATION)' == ''"/>
<Error Text="DeploySource must be a .war or .jar file" Condition="'$(GENERATOR)' == 'Java' AND '%(SourceFile.Extension)' != '.war' AND '%(SourceFile.Extension)' != '.jar'" />
<Error Text="DeploySource must be a .zip file" Condition="('$(GENERATOR)' == 'C#' OR '$(GENERATOR)' == '.NET Framework' OR '$(GENERATOR)' == '.NET Core' or '$(GENERATOR)' == '.NET') AND '%(SourceFile.Extension)' != '.zip'"/>
<Error Text="Missing or invalid GXDeployFileProject property." Condition="'$(GENERATOR)' == 'Java' AND '%(SourceFile.Extension)' == '.jar' AND !Exists('$(GXDeployFileProject)')" />


<PropertyGroup>
<DeployDirectory>%(SourceFile.RootDir)%(SourceFile.Directory)context</DeployDirectory>
<SourceFileName>%(SourceFile.Filename)</SourceFileName>
<Dockerfile>$(DeployDirectory)\Dockerfile</Dockerfile>
<TemplatePath>$(GX_PROGRAM_DIR)\DeploymentTargets\Docker\Templates</TemplatePath>
</PropertyGroup>

<MakeDir Directories="$(DeployDirectory)" Condition="!Exists('DeployDirectory')"/>

<Message Text="$(DeployDirectory)"/>


<!-- Java -->
<PropertyGroup Condition="'$(GENERATOR)' == 'Java' AND '$(IsCMD)' != 'true'">
<WarName Condition=" '$(WarName)' == ''">ROOT</WarName>
<Extension>.war</Extension>
<DockerSource>$(WarName)$(Extension)</DockerSource>
<DockerSourceFullPath>$(DeployDirectory)\$(DockerSource)</DockerSourceFullPath>
<DeployCommand>ADD</DeployCommand>
</PropertyGroup>

<PropertyGroup Condition="'$(GENERATOR)' == 'Java' AND '$(IsCMD)' == 'true'">
<JarName Condition=" '$(JarName)' == ''">$(SourceFileName)</JarName>
<Extension>.jar</Extension>
<DockerSource>$(JarName)$(Extension)</DockerSource>
<DockerSourceFullPath>$(DeployDirectory)\$(DockerSource)</DockerSourceFullPath>
<DeployCommand>ADD</DeployCommand>
</PropertyGroup>


<!-- C# or .NET Core -->
<PropertyGroup Condition="'$(GENERATOR)' == 'C#' OR '$(GENERATOR)' == '.NET Core' OR '$(GENERATOR)' == '.NET Framework' OR '$(GENERATOR)' == '.NET'">
<DeployCommand>COPY</DeployCommand>
<TempDir>$(DeployDirectory)\temp</TempDir>
<DockerSource>temp/</DockerSource>
</PropertyGroup>

<ItemGroup Condition="('$(GENERATOR)' == 'C#' OR '$(GENERATOR)' == '.NET Core' OR '$(GENERATOR)' == '.NET Framework' OR '$(GENERATOR)' == '.NET') AND '$(IsCMD)' == 'true' AND '@(SelectedObject->Count())' == 1">
<ObjectSelected Include="@(SelectedObject->'%(Module).$(MainPrefix)%(Identity)')" Condition="%(SelectedObject.Module) != ''"/>
<ObjectSelected Include="@(SelectedObject->'$(MainPrefix)%(Identity)')" Condition="%(SelectedObject.Module) == ''" />
<ObjectSelectedLower Include="@(ObjectSelected->ToLower())" />
</ItemGroup>

<PropertyGroup Condition="('$(GENERATOR)' == 'C#' OR '$(GENERATOR)' == '.NET Core' OR '$(GENERATOR)' == '.NET Framework' OR '$(GENERATOR)' == '.NET') AND '$(IsCMD)' == 'true' AND '@(SelectedObject->Count())' == 1">
<MainSelected>%(ObjectSelectedLower.Identity)</MainSelected>
</PropertyGroup>


<Copy SourceFiles="$(DeploySource)" DestinationFiles="$(DockerSourceFullPath)" Condition="'$(GENERATOR)' == 'Java'" />

<!-- Copy Java drivers -->
<ItemGroup>
<DependencyFiles Include="$(DeployFullPath)\*" />
<JarDependencies
Include="@(DependencyFiles)"
Condition="'%(Extension)' == '.jar'"
/>
</ItemGroup>

<Copy SourceFiles="@(JarDependencies)" DestinationFiles="@(JarDependencies -> '$(DeployDirectory)\drivers\%(Filename)%(Extension)')" />

<ItemGroup>
<Line Include="# Dockerfile generated by GeneXus ($(GENERATOR))"/>
<Line Include="FROM $(DOCKER_BASE_IMAGE)"/>
<Line Include="LABEL maintainer=&quot;$(DOCKER_MAINTAINER)&quot;" Condition="'$(DOCKER_MAINTAINER)' != ''" />
<Line Include="RUN apt-get update &amp;&amp; apt-get install -y libgdiplus" Condition="('$(GENERATOR)' == '.NET Core' or '$(GENERATOR)' == '.NET') AND '$(OfficeSupport)' == 'true'" />
<Line Include="ENV $(DOCKER_ENVVARS.Replace(';',' '))" Condition="'$(DOCKER_ENVVARS)' != ''" />
<Line Include="WORKDIR $(DOCKER_WEBAPPLOCATION)" />
<Line Include="RUN chgrp -R 0 $(DOCKER_WEBAPPLOCATION) &amp;&amp; chmod -R g=u $(DOCKER_WEBAPPLOCATION)" Condition="'$(DOCKER_CONTAINER_RUNTIME)' == 'Openshift' AND '$(DOCKER_IMAGE_REGISTRY)' == 'DockerHub'" />
<Line Include="RUN [ -d ROOT/ ] &amp;&amp; mv ROOT/ ROOT.old/ || true" Condition="'$(GENERATOR)' == 'Java'" />
<Line Include="$(DeployCommand) [&quot;$(DockerSource)&quot;, &quot;$(DOCKER_WEBAPPLOCATION)&quot;]" />
<Line Include="ENTRYPOINT [&quot;dotnet&quot;, &quot;bin/GxNetCoreStartup.dll&quot;]" Condition="'$(GENERATOR)' == '.NET Core' or '$(GENERATOR)' == '.NET'" />
<Line Include="ADD [&quot;redis/*.jar&quot;, &quot;/usr/local/tomcat/lib/&quot;]" Condition="'$(GENERATOR)' == 'Java' AND '$(K8S_GENERATE_KUBERNETES)' == 'true' AND '$(K8S_ENABLE_REDIS)' == 'true'"/>
<Line Include="ADD [&quot;redis/*.xml&quot;, &quot;/usr/local/tomcat/conf/&quot;]" Condition="'$(GENERATOR)' == 'Java' AND '$(K8S_GENERATE_KUBERNETES)' == 'true' AND '$(K8S_ENABLE_REDIS)' == 'true'"/>
<Line Include="ADD [&quot;redis/redis-data-cache.properties&quot;, &quot;/usr/local/tomcat/conf/&quot;]" Condition="'$(GENERATOR)' == 'Java' AND '$(K8S_GENERATE_KUBERNETES)' == 'true' AND '$(K8S_ENABLE_REDIS)' == 'true'"/>
</ItemGroup>

<ItemGroup>
<LineCMD Include="# Dockerfile generated by GeneXus ($(GENERATOR))"/>
<LineCMD Include="FROM $(DOCKER_BASE_IMAGE)"/>
<LineCMD Include="LABEL maintainer=&quot;$(DOCKER_MAINTAINER)&quot;" Condition="'$(DOCKER_MAINTAINER)' != ''" />
<LineCMD Include="RUN apt-get update &amp;&amp; apt-get install -y libgdiplus" Condition="('$(GENERATOR)' == '.NET Core' or '$(GENERATOR)' == '.NET') AND '$(OfficeSupport)' == 'true'" />
<LineCMD Include="ENV $(DOCKER_ENVVARS.Replace(';',' '))" Condition="'$(DOCKER_ENVVARS)' != ''" />
<LineCMD Include="WORKDIR $(DOCKER_WEBAPPLOCATION)" />
<LineCMD Include="RUN chgrp -R 0 $(DOCKER_WEBAPPLOCATION) &amp;&amp; chmod -R g=u $(DOCKER_WEBAPPLOCATION)" Condition="'$(DOCKER_CONTAINER_RUNTIME)' == 'Openshift' AND '$(DOCKER_IMAGE_REGISTRY)' == 'DockerHub'" />
<LineCMD Include="RUN [ -d ROOT/ ] &amp;&amp; mv ROOT/ ROOT.old/ || true" Condition="'$(GENERATOR)' == 'Java'" />
<LineCMD Include="$(DeployCommand) [&quot;$(DockerSource)&quot;, &quot;$(DOCKER_WEBAPPLOCATION)&quot;]" />
<LineCMD Include="ENTRYPOINT [&quot;dotnet&quot;, &quot;bin/$(MainSelected).dll&quot;]" Condition="('$(GENERATOR)' == '.NET Core' or '$(GENERATOR)' == '.NET') AND $(MainSelected) !=''" />
<LineCMD Include="ENTRYPOINT [&quot;bin/$(MainSelected).exe&quot;]" Condition="('$(GENERATOR)' == 'C#' or '$(GENERATOR)' == '.NET Framework') AND $(MainSelected) !=''" />
<LineCMD Include="ENTRYPOINT [&quot;java&quot;,&quot;-jar&quot;,&quot;$(DockerSource)&quot;]" Condition="'$(GENERATOR)' == 'Java'" />
<LineCMD Include="COPY [&quot;drivers/&quot;, &quot;$(DOCKER_WEBAPPLOCATION)&quot;]" Condition="'$(GENERATOR)' == 'Java'" />
</ItemGroup>

<Message Text="Creating Dockerfile" Importance="high"/>

<WriteLinesToFile File="$(Dockerfile)" Lines="@(Line)" Overwrite="true" Condition="'$(IsCMD)' != 'true'" />
<WriteLinesToFile File="$(Dockerfile)" Lines="@(LineCMD)" Overwrite="true" Condition="'$(IsCMD)' == 'true'" />

</Target>

<Target Name="ExtractZip" Condition="'$(GENERATOR)' == '.NET Core' OR '$(GENERATOR)' == 'C#' or '$(GENERATOR)' == '.NET Framework' or '$(GENERATOR)' == '.NET'">

<Message Text="Extracting application" Importance="high"/>

<RemoveDir Directories="$(TempDir)"/>

<Unzip ZipFileName="$(DeploySource)" TargetDirectory="$(TempDir)"/>

</Target>

<Target Name="RedisSupport" Condition="'$(K8S_GENERATE_KUBERNETES)' == 'true' AND '$(K8S_ENABLE_REDIS)' == 'true'">

<Message Text="Enabling Redis support" Importance="high"/>

<ItemGroup>
<RedisConfig Include="$(GX_PROGRAM_DIR)\DeploymentTargets\Docker\redis\$(GENERATOR)\*.*"/>
</ItemGroup>

<Copy SourceFiles="@(RedisConfig)" DestinationFolder="$(DeployDirectory)\redis\" Condition="'$(K8S_ENABLE_REDIS)' == 'true'"/>

<ItemGroup>
<CSRedis Include="$(DeployDirectory)\redis\CloudServices.redis.config"/>
</ItemGroup>

<XmlPeek XmlInputPath="@(CSRedis)" Query="Services/Service" Condition="Exists('@(CSRedis)')">
<Output TaskParameter="Result" ItemName="RedisService" />
</XmlPeek>

<ItemGroup>
<DestinationCS Include="$(TempDir)\CloudServices.config"/>
</ItemGroup>

<PropertyGroup>
<CloudServiceExists Condition="Exists('@(DestinationCS)')">true</CloudServiceExists>
<CloudServiceExists Condition="!Exists('@(DestinationCS)')">false</CloudServiceExists>
</PropertyGroup>

<XmlPeek XmlInputPath="@(DestinationCS)" Query="Services/Service" Condition="'$(CloudServiceExists)' == 'true'">
<Output TaskParameter="Result" ItemName="OriginalServices" />
</XmlPeek>

</Target>

<Target Name="AppendRedisCS" AfterTargets="RedisSupport" Condition="'@(RedisService->Count())' > 0">

<Message Text="Setting up new CloudServices.config" Importance="high"/>

<WriteLinesToFile File="@(DestinationCS)" Lines="&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;" Overwrite="true" Encoding="UTF-8"/>

<WriteLinesToFile File="@(DestinationCS)" Lines="&lt;Services xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot;&gt;" Overwrite="false"/>

<WriteLinesToFile File="@(DestinationCS)" Lines="@(OriginalServices)" Overwrite="false"/>

<WriteLinesToFile File="@(DestinationCS)" Lines="@(RedisService)" Overwrite="false"/>

<WriteLinesToFile File="@(DestinationCS)" Lines="&lt;/Services&gt;" Overwrite="false"/>

</Target>

<Target Name="ClearRedisAuxiliaryFolder" AfterTargets="AppendRedisCS" Condition="'$(GENERATOR)' != 'Java'">
<RemoveDir Directories="$(DeployDirectory)\redis\"/>
</Target>

<Target Name="GenerateKubernetes" Condition="'$(K8S_GENERATE_KUBERNETES)' == 'true'">

<Message Text="Generating Kubernetes metadata file" Importance="high"/>

<ItemGroup>
<EnvVars Include="$(DOCKER_ENVVARS.Split(';'))"/>
<Labels Include="$(K8S_LABELS.Split(';'))"/>
</ItemGroup>

<PropertyGroup>
<HasEnvVars Condition="'@(EnvVars->Count())' > 0">true</HasEnvVars>
<HasEnvVars Condition="'@(EnvVars->Count())' == 0">false</HasEnvVars>
<HasLabels Condition="'@(Labels->Count())' > 0">true</HasLabels>
<HasLabels Condition="'@(Labels->Count())' == 0">false</HasLabels>
<AppYaml>K8s-$(DeploymentUnit)-App.yaml</AppYaml>
<NamespaceYaml>K8s-$(K8S_NAMESPACE)-Namespace.yaml</NamespaceYaml>
<RedisYaml>K8s-$(K8S_NAMESPACE)-Redis.yaml</RedisYaml>
<AppTemplate>k8s-app.stg</AppTemplate>
<NamespaceTemplate>k8s-namespace.stg</NamespaceTemplate>
<RedisTemplate>k8s-redis.stg</RedisTemplate>
<AppName>$(DeploymentUnit.Replace("_","-").ToLower())</AppName>
</PropertyGroup>

<PropertyGroup Condition="'$(GENERATOR)' == 'Java'">
<ContainerPort>8080</ContainerPort>
</PropertyGroup>

<PropertyGroup Condition="'$(GENERATOR)' == '.NET Core' or '$(GENERATOR)' == '.NET'">
<ContainerPort>80</ContainerPort>
</PropertyGroup>

<Error Text="Environment Variables must be added in the form of key=value." Condition="$(HasEnvVars) AND $([System.String]::new('%(EnvVars.Identity)').IndexOf('=')) == -1" />

<ItemGroup Condition="'$(HasEnvVars)' == 'true'">
<EnvVarsItem Include="@(EnvVars)">
<Index>$([System.String]::new('%(EnvVars.Identity)').IndexOf('='))</Index>
<Key>$([System.String]::new('%(EnvVars.Identity)').Substring(0,$([System.String]::new('%(EnvVars.Identity)').IndexOf('='))))</Key>
<Value>$([System.String]::new('%(EnvVars.Identity)').Substring($([MSBuild]::Add($([System.String]::new('%(EnvVars.Identity)').IndexOf('=')),1))))</Value>
</EnvVarsItem>
</ItemGroup>

<Error Text="Labels must be added in the form of key=value." Condition="$(HasLabels) AND $([System.String]::new('%(Labels.Identity)').IndexOf('=')) == -1" />

<ItemGroup Condition="'$(HasLabels)' == 'true'">
<LabelItem Include="@(Labels)">
<Index>$([System.String]::new('%(Labels.Identity)').IndexOf('='))</Index>
<Key>$([System.String]::new('%(Labels.Identity)').Substring(0,$([System.String]::new('%(Labels.Identity)').IndexOf('='))))</Key>
<Value>$([System.String]::new('%(Labels.Identity)').Substring($([MSBuild]::Add($([System.String]::new('%(Labels.Identity)').IndexOf('=')),1))))</Value>
</LabelItem>
</ItemGroup>

<PropertyGroup>
<K8S_NAMESPACE Condition="'$(K8S_NAMESPACE)' == ''">default</K8S_NAMESPACE>
<HasCustomNamespace Condition="'$(K8S_NAMESPACE)' != 'default'">true</HasCustomNamespace>
<HasCustomNamespace Condition="'$(K8S_NAMESPACE)' == 'default'">false</HasCustomNamespace>
<HasChangeCause Condition="'$(K8S_CHANGE_CAUSE)' != ''">true</HasChangeCause>
<HasChangeCause Condition="'$(K8S_CHANGE_CAUSE)' == ''">false</HasChangeCause>
</PropertyGroup>

<GenerateFromTemplate Condition="'$(K8S_ENABLE_REDIS)' == 'true'" TemplateGroupFile="$(TemplatePath)\$(RedisTemplate)" TemplateName="generate" Properties="AppName=$(AppName);HasCustomNamespace=$(HasCustomNamespace);CustomNamespace=$(K8S_NAMESPACE)" OutputFile="$(DeployDirectory)\$(RedisYaml)"/>

<Message Condition="'$(K8S_ENABLE_REDIS)' == 'true'" Text="Metadata Redis file succesfully generated at '$(DeployDirectory)\$(RedisYaml)'" Importance="high"/>

<GenerateFromTemplate Condition="'$(HasCustomNamespace)' == 'true'" TemplateGroupFile="$(TemplatePath)\$(NamespaceTemplate)" TemplateName="generate" Properties="HasCustomNamespace=$(HasCustomNamespace);CustomNamespace=$(K8S_NAMESPACE)" OutputFile="$(DeployDirectory)\$(NamespaceYaml)"/>

<Message Condition="'$(HasCustomNamespace)' == 'true'" Text="Metadata Namespace file succesfully generated at '$(DeployDirectory)\$(NamespaceYaml)'" Importance="high"/>

<GenerateFromTemplate TemplateGroupFile="$(TemplatePath)\$(AppTemplate)" TemplateName="generate" Properties="DeploymentUnit=$(DeploymentUnit);serviceType=$(K8S_SERVICE_TYPE);containerPort=$(ContainerPort);replicas=$(K8S_INITIAL_REPLICAS);imageTag=$(DOCKER_IMAGE_NAME);HasEnvVars=$(HasEnvVars);EnableRedis=$(K8S_ENABLE_REDIS);AppName=$(AppName);Generator=$(GENERATOR);HasCustomNamespace=$(HasCustomNamespace);CustomNamespace=$(K8S_NAMESPACE);HasChangeCause=$(HasChangeCause);ChangeCause=$(K8S_CHANGE_CAUSE);HasLabels=$(HasLabels)"
Items="@(EnvVarsItem);@(LabelItem)" ItemTypes="@(EnvVarsItem -> 'EnvVarsItems[]');@(LabelItem -> 'LabelItems[]')" OutputFile="$(DeployDirectory)\$(AppYaml)"/>

<Message Text="Kubernetes metadata file succesfully generated at '$(DeployDirectory)\$(AppYaml)'" Importance="high"/>

</Target>

<Target Name="CreatePackage" DependsOnTargets="ValidatePackaging;CreateDockerfile;ExtractZip;RedisSupport;GenerateKubernetes" />

<Target Name="ValidatePackaging">

<Error Text="DeploySource cannot be empty" Condition="'$(DeploySource)' == ''"/>

<Error Text="The deployment unit must have only one command line procedure." Condition="'@(SelectedObject->Count())' &gt; 1 AND '$(IsCMD)' == 'true'"/>

<Warning
Text="Missing or invalid GXDeployFileProject property. It should be set for command line deployments."
Condition="('$(GENERATOR)' == 'C#' OR '$(GENERATOR)' == '.NET Framework' OR '$(GENERATOR)' == '.NET Core' or '$(GENERATOR)' == '.NET') AND !Exists('$(GXDeployFileProject)')" />

</Target>

</Project>
Loading

0 comments on commit a654a0c

Please sign in to comment.