<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Frederic</title>
    <description>The latest articles on DEV Community by Frederic (@fredericheem).</description>
    <link>https://dev.to/fredericheem</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F607313%2F24cf7c4a-eb7c-4d23-944f-4cfd28e65f47.jpeg</url>
      <title>DEV Community: Frederic</title>
      <link>https://dev.to/fredericheem</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fredericheem"/>
    <language>en</language>
    <item>
      <title>Full Stack App Automated deployment on AWS EKS</title>
      <dc:creator>Frederic</dc:creator>
      <pubDate>Fri, 02 Jul 2021 16:37:27 +0000</pubDate>
      <link>https://dev.to/fredericheem/full-stack-app-automated-deployment-on-aws-eks-3m19</link>
      <guid>https://dev.to/fredericheem/full-stack-app-automated-deployment-on-aws-eks-3m19</guid>
      <description>&lt;h1&gt;
  
  
  Full Stack Application on AWS EKS
&lt;/h1&gt;

&lt;p&gt;This example automatically deploys a full-stack application with Kubernetes on AWS using their managed control plane called &lt;a href="https://aws.amazon.com/eks/" rel="noopener noreferrer"&gt;Elastic Kubernetes Service&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Automation is performed with &lt;a href="https://grucloud.com" rel="noopener noreferrer"&gt;GruCloud&lt;/a&gt;, which is an infrastructure as code tool written in Javascript.&lt;/p&gt;

&lt;h2&gt;
  
  
  High-level description
&lt;/h2&gt;

&lt;p&gt;This infrastructure combines 2 providers: AWS and Kubernetes.&lt;/p&gt;

&lt;p&gt;A few modules for each of these providers are being used:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Fstarhackit%2Feks-lean%2Fmodules.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Fstarhackit%2Feks-lean%2Fmodules.svg" alt="module.svg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example, the load balancer, target groups, listeners, and rules are managed by GruCloud instead of the &lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/aws-load-balancer-controller.html" rel="noopener noreferrer"&gt;AWS Load Balancer Controller&lt;/a&gt;.&lt;br&gt;
The benefit of not using the LBC is to free a lot of resources, the LBC depends on the &lt;a href="https://cert-manager.io/" rel="noopener noreferrer"&gt;Cert Manager&lt;/a&gt; which brings more resources,&lt;br&gt;
By not using the AWS LBC and the Cert Manager, we can save 4 pods, and numerous other resources such as ServiceAcount, ClusterRole, ClusterRoleBinding, we can even get rid of the CRD stuff.&lt;br&gt;
Fewer pods mean we can choose a cheaper worker node.&lt;/p&gt;
&lt;h3&gt;
  
  
  Modules for AWS resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@grucloud/module-aws-certificate" rel="noopener noreferrer"&gt;module-aws-certificate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@grucloud/module-aws-vpc" rel="noopener noreferrer"&gt;module-aws-vpc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@grucloud/module-aws-eks" rel="noopener noreferrer"&gt;module-aws-eks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@grucloud/module-aws-load-balancer" rel="noopener noreferrer"&gt;module-aws-load-balancer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Modules for K8s resources
&lt;/h3&gt;

&lt;p&gt;The local module defining the app on the k8s side is located at &lt;a href="https://github.com/grucloud/grucloud/tree/main/examples/starhackit/base" rel="noopener noreferrer"&gt;base&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There is no trace of manifests in YAML, instead, Kubernetes manifests are described in Javascript, allowing the use of variables, conditionals, loops, importing code, and even the use of a debugger. Therefore, GruCloud is an alternative to &lt;em&gt;helm&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;p&gt;From the infrastructure code, 2 kinds of visual representation can be generated with the GruCloud CLI &lt;strong&gt;gc&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a mind map indicating the type of the resource: &lt;code&gt;gc tree&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;a diagram showing the relationship between the resources: &lt;code&gt;gc graph&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Mindmap
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Fstarhackit%2Feks-lean%2Fresources-mindmap.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Fstarhackit%2Feks-lean%2Fresources-mindmap.svg" alt="resources-mindmap.svg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Diagram
&lt;/h4&gt;

&lt;p&gt;The following &lt;a href="https://raw.githubusercontent.com/grucloud/grucloud/main/examples/starhackit/eks-lean/diagram-target.svg" rel="noopener noreferrer"&gt;diagram&lt;/a&gt; shows the AWS and K8s resources and their relashionship:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Fstarhackit%2Feks-lean%2Fdiagram-target.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Fstarhackit%2Feks-lean%2Fdiagram-target.svg" alt="diagram-target.svg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Workflow
&lt;/h2&gt;

&lt;p&gt;The next flowchart tells the actions to perform to configure, deploy, update and destroy this infrastructure:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Fstarhackit%2Feks-lean%2Feks-lean-workflow.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Fstarhackit%2Feks-lean%2Feks-lean-workflow.svg" alt="EKS full stack"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Requirements
&lt;/h3&gt;
&lt;h4&gt;
  
  
  AWS CLI
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fdocusaurus%2Fplantuml%2Faws-requirements.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fdocusaurus%2Fplantuml%2Faws-requirements.svg" alt="AWS Requirements"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  GruCloud CLI:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fdocusaurus%2Fplantuml%2Fgrucloud-cli-install.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fdocusaurus%2Fplantuml%2Fgrucloud-cli-install.svg" alt="gc-cli-install"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Getting the source code
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fdocusaurus%2Fplantuml%2Fgrucloud-project-setup.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fdocusaurus%2Fplantuml%2Fgrucloud-project-setup.svg" alt="project-setup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This example is located at &lt;code&gt;examples/starhackit/eks-lean&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Amazon EKS
&lt;/h4&gt;

&lt;p&gt;The first part of this deployment is to create an EKS control plane, a node group for the workers, and all their numerous dependencies.&lt;/p&gt;

&lt;p&gt;Configuration for the AWS resources is located at &lt;a href="https://raw.githubusercontent.com/grucloud/grucloud/main/examples/starhackit/eks-lean/configAws.js" rel="noopener noreferrer"&gt;configAws.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set the &lt;strong&gt;rootDomainName&lt;/strong&gt; and &lt;strong&gt;domainName&lt;/strong&gt; according to your use case&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For end-to-end automation, the &lt;strong&gt;rootDomainName&lt;/strong&gt; should be registered or transferred to the AWS Route53 service.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;
  
  
  K8s
&lt;/h4&gt;

&lt;p&gt;The second part is the Kubernetes deployment of the full-stack application composed of a React front end, a Node backend, Postgres as the SQL database, and finally Redis for the cache and published/subscriber models.&lt;/p&gt;

&lt;p&gt;Configuration for the K8s resources is located at &lt;a href="https://raw.githubusercontent.com/grucloud/grucloud/main/examples/starhackit/eks-lean/configK8s.js" rel="noopener noreferrer"&gt;configK8s.js&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When the backend container is changed to another backend, do not forget to change the target group health check in &lt;strong&gt;configAWS.js&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  GruCloud workflow
&lt;/h3&gt;

&lt;p&gt;This chart depicts the workflow with the main &lt;strong&gt;gc&lt;/strong&gt; commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gc info&lt;/li&gt;
&lt;li&gt;gc graph&lt;/li&gt;
&lt;li&gt;gc apply&lt;/li&gt;
&lt;li&gt;gc list&lt;/li&gt;
&lt;li&gt;gc destroy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fdocusaurus%2Fplantuml%2Fgrucloud-cli-commands.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fdocusaurus%2Fplantuml%2Fgrucloud-cli-commands.svg" alt="grucloud commands"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Listing
&lt;/h4&gt;

&lt;p&gt;Let's find out if everything is set up properly by listing the live resources from AWS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Listing resources on 2 providers: aws, k8s
✓ aws
  ✓ Initialising
  ✓ Listing 29/29
k8s
  Initialising
  Listing 0/8
List Summary:
Provider: aws
┌───────────────────────────────────────────────────────────────────────────────────────────────┐
│ aws                                                                                           │
├────────────────────┬──────────────────────────────────────────────────────────────────────────┤
│ IamPolicy          │ AmazonEKSClusterPolicy                                                   │
│                    │ AmazonEKSVPCResourceController                                           │
│                    │ AmazonEKSWorkerNodePolicy                                                │
│                    │ AmazonEC2ContainerRegistryReadOnly                                       │
│                    │ AmazonEKS_CNI_Policy                                                     │
├────────────────────┼──────────────────────────────────────────────────────────────────────────┤
│ Route53Domain      │ grucloud.org                                                             │
├────────────────────┼──────────────────────────────────────────────────────────────────────────┤
│ Vpc                │ default                                                                  │
├────────────────────┼──────────────────────────────────────────────────────────────────────────┤
│ InternetGateway    │ igw-9c2f1ae7                                                             │
├────────────────────┼──────────────────────────────────────────────────────────────────────────┤
│ SecurityGroup      │ default                                                                  │
├────────────────────┼──────────────────────────────────────────────────────────────────────────┤
│ Subnet             │ default                                                                  │
│                    │ default                                                                  │
│                    │ default                                                                  │
│                    │ default                                                                  │
│                    │ default                                                                  │
│                    │ default                                                                  │
├────────────────────┼──────────────────────────────────────────────────────────────────────────┤
│ RouteTable         │ rtb-19753867                                                             │
└────────────────────┴──────────────────────────────────────────────────────────────────────────┘
19 resources, 8 types, 1 provider
Command "gc l" executed in 5s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the presence of a default VPC, subnets, security group, and internet gateway.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Verify that the domain name is registered with Route53Domain, in this case, &lt;em&gt;grucloud.org&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Kubernetes control created by EKS is not up yet, as a consequence, listing the k8s resources cannot be retrieved at this stage.&lt;/p&gt;

&lt;h4&gt;
  
  
  Deploying
&lt;/h4&gt;

&lt;p&gt;It is show time for deploying all the AWS and Kubernetes resources in one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The app should be now running with Kubernetes on AWS after 15 minutes.&lt;/p&gt;

&lt;p&gt;When all the resources are created, custom code can be invoked in &lt;a href="//./hook.js"&gt;hook.js&lt;/a&gt;.&lt;br&gt;
In this example, we verify access to the webserver and the API server securely.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;kubeconfig&lt;/em&gt; has been updated with the endpoint from the EKS cluster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl config current-context
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;arn:aws:eks:eu-west-2:999541460000:cluster/cluster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's list and produce a diagram of the AWS resources freshly created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc list &lt;span class="nt"&gt;-p&lt;/span&gt; aws &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;--default-exclude&lt;/span&gt; &lt;span class="nt"&gt;--types-exclude&lt;/span&gt; Certificate &lt;span class="nt"&gt;--types-exclude&lt;/span&gt; Route53Domain &lt;span class="nt"&gt;--types-exclude&lt;/span&gt; NetworkInterface
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Fstarhackit%2Feks-lean%2Fdiagram-live.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Fstarhackit%2Feks-lean%2Fdiagram-live.svg" alt="diagram-live.svg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that the &lt;em&gt;NodeGroup&lt;/em&gt; has created an &lt;em&gt;AutoScaling Group&lt;/em&gt;, which in turn creates EC2 instances, instance profiles, and volumes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Updating
&lt;/h4&gt;

&lt;p&gt;Let's update the cluster with another version of the front end.&lt;br&gt;
Edit &lt;a href="https://raw.githubusercontent.com/grucloud/grucloud/main/examples/starhackit/eks-lean/configK8s.js" rel="noopener noreferrer"&gt;configK8s.js&lt;/a&gt; and change the frontend version.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;gc apply&lt;/code&gt; command will find out the difference between the expected version and the deployed version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Querying resources on 2 providers: aws, k8s
✓ aws
  ✓ Initialising
  ✓ Listing 30/30
  ✓ Querying
    ✓ HostedZone 1/1
    ✓ Certificate 1/1
    ✓ Route53Record 2/2
    ✓ Vpc 1/1
    ✓ InternetGateway 1/1
    ✓ Subnet 4/4
    ✓ RouteTable 3/3
    ✓ Route 3/3
    ✓ ElasticIpAddress 1/1
    ✓ NatGateway 1/1
    ✓ IamRole 2/2
    SecurityGroup 3/4
    ✓ SecurityGroupRuleIngress 6/6
    ✓ SecurityGroupRuleEgress 1/1
    ✓ KmsKey 1/1
    ✓ EKSCluster 1/1
    ✓ EKSNodeGroup 1/1
    ✓ LoadBalancer 1/1
    ✓ TargetGroup 2/2
    ✓ Listener 2/2
    ✓ Rule 3/3
✓ k8s
  ✓ Initialising
  ✓ Listing 8/8
  ✓ Querying
    ✓ Namespace 1/1
    ✓ ConfigMap 2/2
    ✓ StatefulSet 2/2
    ✓ Service 4/4
    ✓ Deployment 2/2
┌────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 1 Deployment from k8s                                                                              │
├────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌───────────────────────────────────────────────────────────────────────────────────────────────┐  │
│ │ UPDATE: name: default::web, id: web                                                           │  │
│ ├───────────────────────────────────────────────────────────────────────────────────────────────┤  │
│ │ Key: spec                                                                                     │  │
│ ├───────────────────────────────────────────────┬───────────────────────────────────────────────┤  │
│ │ - template:                                   │ + template:                                   │  │
│ │   spec:                                       │   spec:                                       │  │
│ │     containers:                               │     containers:                               │  │
│ │       0:                                      │       0:                                      │  │
│ │         image: fredericheem/ui:v10.14.0       │         image: fredericheem/ui:v10.15.0       │  │
│ │                                               │                                               │  │
│ └───────────────────────────────────────────────┴───────────────────────────────────────────────┘  │
└────────────────────────────────────────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────────────────────────────┐
│ Plan summary for provider aws                                                               │
└─────────────────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────────────────┐
│ Plan summary for provider k8s                                                               │
├─────────────────────────────────────────────────────────────────────────────────────────────┤
│ DEPLOY RESOURCES                                                                            │
├────────────────────┬────────────────────────────────────────────────────────────────────────┤
│ Deployment         │ default::web                                                           │
└────────────────────┴────────────────────────────────────────────────────────────────────────┘
? Are you sure to deploy 1 resource, 1 type on 1 provider? › (y/N)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is the equivalent of &lt;code&gt;kubectl apply&lt;/code&gt;, except that &lt;code&gt;kubectl&lt;/code&gt; is "fire and forget", but &lt;em&gt;gc&lt;/em&gt; apply the changes and waits for the resources to be ready before returning.&lt;/p&gt;

&lt;h4&gt;
  
  
  Destroying
&lt;/h4&gt;

&lt;p&gt;Running Kubernetes cluster on AWS or other cloud providers is not cheap. Stop paying when the cluster is not used with one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Resources will be destroyed in the right order and automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/grucloud/grucloud" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com/docs/Introduction" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/grucloud_iac" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
    <item>
      <title>Deploy an HTTPS Static Website on GCP with GruCloud</title>
      <dc:creator>Frederic</dc:creator>
      <pubDate>Wed, 30 Jun 2021 18:55:51 +0000</pubDate>
      <link>https://dev.to/fredericheem/deploy-https-static-website-on-gcp-with-grucloud-4ojb</link>
      <guid>https://dev.to/fredericheem/deploy-https-static-website-on-gcp-with-grucloud-4ojb</guid>
      <description>&lt;h2&gt;
  
  
  Hosting a secure static website on GCP, domain managed by AWS Route53
&lt;/h2&gt;

&lt;p&gt;The goal of this example is to automate with &lt;a href="https://grucloud.com"&gt;GruCloud&lt;/a&gt;, the deployment of a static website served with HTTPS on GCP, the Google Cloud Platform.&lt;/p&gt;

&lt;p&gt;The domain and DNS settings are handled by &lt;em&gt;AWS Route53&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;See the manual way at &lt;a href="https://cloud.google.com/storage/docs/hosting-static-website"&gt;hosting static website&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://domains.google/"&gt;Google Domain&lt;/a&gt; does not provide API, and the other google DNS service &lt;a href="https://cloud.google.com/domains/docs/overview"&gt;Cloud Domain&lt;/a&gt; does not support transferring a domain.&lt;/p&gt;

&lt;p&gt;For this reason, this example uses &lt;em&gt;AWS Route53&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;This deployment is composed of the resources depicted in the following diagram:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YdeaXOGw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/examples/google/storage/website-https/diagram-target.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YdeaXOGw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/examples/google/storage/website-https/diagram-target.svg" alt="GraphTarget"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The command &lt;code&gt;gc graph&lt;/code&gt; generates this diagram from the code &lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/google/storage/website-https/iac.js"&gt;iac.js&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Below are the links to the resource documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com/docs/google/resources/storage/GcpObject"&gt;Object&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com/docs/google/resources/storage/GcpBucket"&gt;Bucket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com/docs/google/resources/Compute/BackendBucket"&gt;Backend Bucket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com/docs/google/resources/Compute/GlobalForwardingRule"&gt;Global Forwarding Rule&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com/docs/google/resources/Compute/HttpsTargetProxy"&gt;Https Target Proxy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com/docs/google/resources/Compute/SslCertificate"&gt;SSL Certificate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com/docs/google/resources/Compute/UrlMap"&gt;Url Map&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Hooks
&lt;/h2&gt;

&lt;p&gt;The file &lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/google/storage/website-https/hook.js"&gt;hook.js&lt;/a&gt; contains actions to perform after the infrastructure is deployed and after it is destroyed.&lt;/p&gt;

&lt;p&gt;The file &lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/google/storage/website-https/route53Utils.js"&gt;route53Utils.js&lt;/a&gt; contains functions to add and remove a DNS record of type A to map the domain name to the load balancer's IP address by calling the AWS CLI.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;aws route53 list-hosted-zones-by-name --dns-name ${domainName}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;aws route53 list-resource-record-sets --hosted-zone-id ${hostedZoneId}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;aws route53 change-resource-record-sets --hosted-zone-id ${hostedZoneId} --change-batch '${changeBatch}'&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;h3&gt;
  
  
  GruCloud CLI
&lt;/h3&gt;

&lt;p&gt;Ensure &lt;strong&gt;gc&lt;/strong&gt;, the GruCloud CLI is installed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IT6j7k88--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/docusaurus/plantuml/grucloud-cli-install.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IT6j7k88--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/docusaurus/plantuml/grucloud-cli-install.svg" alt="cli"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  GCP
&lt;/h3&gt;

&lt;p&gt;Follow this flowchart to install and configure the &lt;code&gt;gcloud&lt;/code&gt; CLI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o4Fg4yKT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/docusaurus/plantuml/gcp-requirements.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o4Fg4yKT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/docusaurus/plantuml/gcp-requirements.svg" alt="gcp-requirements"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS
&lt;/h3&gt;

&lt;p&gt;Ensure the AWS CLI is installed as it will be invoked in the &lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/google/storage/website-https/hook.js"&gt;hook.js&lt;/a&gt; to add and remove a DNS record to map the domain name to the load balancer's IP address.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z49uc8yq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/docusaurus/plantuml/aws-requirements.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z49uc8yq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/docusaurus/plantuml/aws-requirements.svg" alt="AWS Requirements"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Route53 Domain
&lt;/h3&gt;

&lt;p&gt;Let's verify that the AWS account has a domain name registered:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws route53domains list-domains &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Domains": [
        {
            "DomainName": "grucloud.org",
            "AutoRenew": true,
            "TransferLock": false,
            "Expiry": "2021-11-16T13:56:10+01:00"
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, see the &lt;a href="https://console.aws.amazon.com/route53/home#DomainListing"&gt;Route53 Domain Listing&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Route53 Hosted Zone
&lt;/h3&gt;

&lt;p&gt;Create a Hosted Zone, later on, a DNS record of type A will be created in this zone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws route53 create-hosted-zone &lt;span class="nt"&gt;--name&lt;/span&gt; grucloud.org &lt;span class="nt"&gt;--caller-reference&lt;/span&gt; 2021-06-30-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You could also visit the &lt;a href="https://console.aws.amazon.com/route53/v2/home#Dashboard"&gt;Route53 Dashboard&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting the source code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JC0pRwxu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/docusaurus/plantuml/grucloud-project-setup.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JC0pRwxu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/docusaurus/plantuml/grucloud-project-setup.svg" alt="project-setup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This example is located at &lt;code&gt;examples/google/storage/website-https&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Config
&lt;/h2&gt;

&lt;p&gt;Edit &lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/google/storage/website-https/config.js"&gt;config.js&lt;/a&gt; and set the following variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;projectId&lt;/em&gt;: the project Id, must be unique, see restrictions &lt;a href="https://cloud.google.com/resource-manager/docs/creating-managing-projects#:~:text=The%20project%20ID%20must%20be,used%20for%20a%20deleted%20project."&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;bucketName&lt;/em&gt;: the bucket name which is also the domain name, i.e. mywebsite.com or subdomain.mywebsite.com, see the &lt;a href="https://cloud.google.com/storage/docs/naming-buckets"&gt;bucket naming guideline&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;hostedZoneName&lt;/em&gt;: the hosted zone name in Route53, i.e. mywebsite.com&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;websiteDir&lt;/em&gt;: the directory containing the static website.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Initialise
&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;init&lt;/em&gt; command will create the project, set up the billing, enable the API services, create the service account and its credentials file, and bind the IAM roles to this service account&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gc init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SeqTcYmp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/docusaurus/plantuml/gcp-provider-init.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SeqTcYmp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/docusaurus/plantuml/gcp-provider-init.svg" alt="gc-init-gcp"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Add the service account as the domain owner
&lt;/h2&gt;

&lt;p&gt;The service account operating by &lt;em&gt;grucloud&lt;/em&gt; needs to be added as the domain owner.&lt;/p&gt;

&lt;p&gt;This service account created previously with the &lt;strong&gt;init&lt;/strong&gt; command is in the form of grucloud@&lt;strong&gt;YourProjectId&lt;/strong&gt;.iam.gserviceaccount.com&lt;/p&gt;

&lt;p&gt;This service account is also stored in the generated credential file as the &lt;strong&gt;client_email&lt;/strong&gt; property.&lt;br&gt;
To find out where the credential file is located:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  - provider:
      name: google
      type: google
    stage: dev
    projectId: grucloud-test
    projectName: grucloud-test
    applicationCredentialsFile: /Users/yourusername/.config/gcloud/your-project-id.json
    serviceAccountName: grucloud
    hasGCloud: true
    config:
      bucketName: grucloud.org
      websiteDir: ./websites/simple
      managedByTag: -managed-by-gru
      managedByKey: managed-by
      managedByValue: grucloud
      region: europe-west4
      zone: europe-west4-a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow the manual steps at the &lt;a href="https://cloud.google.com/storage/docs/domain-name-verification"&gt;domain name verification documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  GruCloud CLI Workflow
&lt;/h2&gt;

&lt;p&gt;This chart shows the GruCloud CLI main commands:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SuQ_IYHf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/docusaurus/plantuml/grucloud-cli-commands.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SuQ_IYHf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/docusaurus/plantuml/grucloud-cli-commands.svg" alt="gc-work-flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy
&lt;/h3&gt;

&lt;p&gt;Deploy this infrastructure with the &lt;em&gt;apply&lt;/em&gt; command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Querying resources on 1 provider: google
✓ google
  ✓ Initialising
  ✓ Listing 7/7
  ✓ Querying
    ✓ Bucket 1/1
    ✓ Object 1/1
    ✓ SslCertificate 1/1
    ✓ BackendBucket 1/1
    ✓ UrlMap 1/1
    ✓ HttpsTargetProxy 1/1
    ✓ GlobalForwardingRule 1/1
┌────────────────────────────────────────────────────────────────────┐
│ Plan summary for provider google                                   │
├────────────────────────────────────────────────────────────────────┤
│ DEPLOY RESOURCES                                                   │
├────────────────────┬───────────────────────────────────────────────┤
│ Bucket             │ grucloud.org                                  │
├────────────────────┼───────────────────────────────────────────────┤
│ Object             │ index.html                                    │
├────────────────────┼───────────────────────────────────────────────┤
│ SslCertificate     │ ssl-certificate                               │
├────────────────────┼───────────────────────────────────────────────┤
│ BackendBucket      │ backend-bucket                                │
├────────────────────┼───────────────────────────────────────────────┤
│ UrlMap             │ url-map                                       │
├────────────────────┼───────────────────────────────────────────────┤
│ HttpsTargetProxy   │ https-target-proxy                            │
├────────────────────┼───────────────────────────────────────────────┤
│ GlobalForwardingR… │ global-forwarding-rule                        │
└────────────────────┴───────────────────────────────────────────────┘
Deploying resources on 1 provider: google
✓ google
  ✓ Initialising
  ✓ Deploying
    ✓ Bucket 1/1
    ✓ Object 1/1
    ✓ SslCertificate 1/1
    ✓ BackendBucket 1/1
    ✓ UrlMap 1/1
    ✓ HttpsTargetProxy 1/1
    ✓ GlobalForwardingRule 1/1
  ✓ default::onDeployed
    ✓ add dns record for the load balancer
    ✓ get https://storage.googleapis.com/grucloud.org/index.html
    ✓ get https://storage.googleapis.com/grucloud.org
    ✓ ssl certificate ready
    ✓ get https://grucloud.org
7 resources deployed of 7 types and 1 provider
Running OnDeployedGlobal resources on 1 provider: google
Command "gc a -f" executed in 11m 48s
fredericheem@pc7 website-https %
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the end of the deployment of the GCP resources, the &lt;em&gt;onDeployed&lt;/em&gt; hook is invoked.&lt;/p&gt;

&lt;p&gt;First, a DNS type A record is added to map the domain name to the load balancer's IPv4 address, i.e the &lt;em&gt;GlobalForwardingRule&lt;/em&gt; resource.&lt;/p&gt;

&lt;p&gt;The SSL certificate is waiting for this record to verify the ownership of the domain. It may take a few minutes for the SSL certificate to be ready.&lt;/p&gt;

&lt;p&gt;The last stage is to get the webpage with HTTPS.&lt;br&gt;
It ensures the deployment is completed successfully.&lt;/p&gt;
&lt;h3&gt;
  
  
  List the resources.
&lt;/h3&gt;

&lt;p&gt;Verity the state of the resource with the &lt;strong&gt;gc list&lt;/strong&gt; command, the &lt;em&gt;--graph&lt;/em&gt; generates a graph of the live resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc list &lt;span class="nt"&gt;--graph&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x_N6hU3d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/examples/google/storage/website-https/diagram-live.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x_N6hU3d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/examples/google/storage/website-https/diagram-live.svg" alt="GraphLive"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Listing resources on 1 provider: google
✓ google
  ✓ Initialising
  ✓ Listing 7/7
┌─────────────────────────────────────────────────────────────────────┐
│ 1 SslCertificate from google                                        │
├─────────────────┬────────────────────────────────────────────┬──────┤
│ Name            │ Data                                       │ Our  │
├─────────────────┼────────────────────────────────────────────┼──────┤
│ ssl-certificate │ id: 6441474765553268206                    │ Yes  │
│                 │ creationTimestamp: 2021-06-30T03:44:17.99… │      │
│                 │ name: ssl-certificate                      │      │
│                 │ description: Managed By GruCloud           │      │
│                 │ selfLink: https://www.googleapis.com/comp… │      │
│                 │ certificate: -----BEGIN CERTIFICATE-----   │      │
│                 │ MIIFUTCCBDmgAwIBAgIRAPkAAOJC7+5VCgAAAADtD… │      │
│                 │ RjELMAkGA1UEBhMCVVMxIjAgBgNVBAoTGUdvb2dsZ… │      │
│                 │ TEMxEzARBgNVBAMTCkdUUyBDQSAxRDQwHhcNMjEwN… │      │
│                 │ MTA0ODQyWjAXMRUwEwYDVQQDEwxncnVjbG91ZC5vc… │      │
│                 │ AQUAA4IBDwAwggEKAoIBAQCwg05xlwu+1ypsJgQ5W… │      │
│                 │ I6TrqTwTpTq8lIwpEBvksGz2w99nJ5lLiCBhH7MRW… │      │
│                 │ 4z4l7D+s/u8xCe7XB2D/B6suXPdVpPjl21kHLQUQC… │      │
│                 │ dwrlJS4M3KfRYXhesJxZEeO3+PoXKw3wBkIpSRfvk… │      │
│                 │ jqdpROyJRaJ/gH1/1Ixe9wxQ0xRf9jAZClyfL8M/D… │      │
│                 │ aQiL+jB/x1AJYwuud04PPZuBNE3ouln8UnD5MD65C… │      │
│                 │ BgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBB… │      │
│                 │ ADAdBgNVHQ4EFgQUn0Lwt6ba79AHuJDIGAlW2310Y… │      │
│                 │ DrJXkZQq5dRdhpCD3lOzuJIwagYIKwYBBQUHAQEEX… │      │
│                 │ dHRwOi8vb2NzcC5wa2kuZ29vZy9ndHMxZDQwMQYIK… │      │
│                 │ a2kuZ29vZy9yZXBvL2NlcnRzL2d0czFkNC5kZXIwF… │      │
│                 │ dWQub3JnMCEGA1UdIAQaMBgwCAYGZ4EMAQIBMAwGC… │      │
│                 │ BDUwMzAxoC+gLYYraHR0cDovL2NybHMucGtpLmdvb… │      │
│                 │ V0NrLmNybDCCAQYGCisGAQQB1nkCBAIEgfcEgfQA8… │      │
│                 │ Vo7jTRMZM7/fDC8gC8xO8WTjAAABelyN0mYAAAQDA… │      │
│                 │ 64j1+EfMUP7z2a1r49DvMLeIKdM1AiEA/JSBRq8oP… │      │
│                 │ POCDVgsI/BQAdwDuwJXujXJkD5Ljw7kbxxKjaWoJe… │      │
│                 │ jdKCAAAEAwBIMEYCIQDoxrQxCcEH2vVeg2AtstxI1… │      │
│                 │ AOsmu4oulyYswA7MTs/Dy29W+nXk0D0mGAOzAHkCz… │      │
│                 │ A4IBAQAoD2cok3xHy87yVKdF7NUtjVAS6/jB6/KUd… │      │
│                 │ ZXvfhKYWZuc9WCaEUNZo45y582uuf/Wv1dBXSiH6v… │      │
│                 │ fsiQzTeOA5+5EmnQLkvaSpfs1VgMwwc0w+bd3mhHa… │      │
│                 │ NlSHP9oWk4Y4sk9ngaDu6p+nilPNXpKOXeVWchB5f… │      │
│                 │ fSjfQ5lMpeZMQi68FPuiNkcaJ5CY0ntHcwenhUpew… │      │
│                 │ 7hT0UnMmPf21WKP4EdMmmw+4dHwx               │      │
│                 │ -----END CERTIFICATE-----                  │      │
│                 │ -----BEGIN CERTIFICATE-----                │      │
│                 │ MIIFjDCCA3SgAwIBAgINAgCOsgIzNmWLZM3bmzANB… │      │
│                 │ CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRyd… │      │
│                 │ MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMjAwODEzM… │      │
│                 │ MDQyWjBGMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR… │      │
│                 │ Y2VzIExMQzETMBEGA1UEAxMKR1RTIENBIDFENDCCA… │      │
│                 │ ggEPADCCAQoCggEBAKvAqqPCE27l0w9zC8dTPIE89… │      │
│                 │ UebUQpK0yv2r678RJExK0HWDjeq+nLIHN1Em5j6rA… │      │
│                 │ saztIIJ7O0g/82qj/vGDl//3t4tTqxiRhLQnTLXJd… │      │
│                 │ H3Rcsejcqj8p5Sj19vBm6i1FhqLGymhMFroWVUGO3… │      │
│                 │ 2190Q0Lm/SiKmLbRJ5Au4y1euFJm2JM9eB84Fkqa3… │      │
│                 │ zvxtxvusLJzLWYHk55zcRAacDA2SeEtBbQfD1qsCA… │      │
│                 │ DwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDA… │      │
│                 │ AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUJeIYDrJXk… │      │
│                 │ VR0jBBgwFoAU5K8rJnEaK0gnhS9SZizv8IkTcT4wa… │      │
│                 │ CCsGAQUFBzABhhpodHRwOi8vb2NzcC5wa2kuZ29vZ… │      │
│                 │ AoYkaHR0cDovL3BraS5nb29nL3JlcG8vY2VydHMvZ… │      │
│                 │ MCswKaAnoCWGI2h0dHA6Ly9jcmwucGtpLmdvb2cvZ… │      │
│                 │ A1UdIARGMEQwCAYGZ4EMAQIBMDgGCisGAQQB1nkCB… │      │
│                 │ aHR0cHM6Ly9wa2kuZ29vZy9yZXBvc2l0b3J5LzANB… │      │
│                 │ IVToy24jwXUr0rAPc924vuSVbKQuYw3nLflLfLh5A… │      │
│                 │ FZbhXkBH0PNcw97thaf2BeoDYY9Ck/b+UGluhx06z… │      │
│                 │ K+Xh3I0tqJy2rgOqNDflr5IMQ8ZTWA3yltakzSBKZ… │      │
│                 │ uPCJvscp1/m2pVTtyBjYPRQ+QuCQGAJKjtN7R5DFr… │      │
│                 │ 3cTIfzE7cmALskMKNLuDz+RzCcsYTsVaU7Vp3xL60… │      │
│                 │ YgPmOT4X3+7L51fXJyRH9KfLRP6nT31D5nmsGAOgZ… │      │
│                 │ VS5H0HyIBMEKyGMIPhFWrlt/hFS28N1zaKI0ZBGD3… │      │
│                 │ lVlWPzXe81vdoEnFbr5M272HdgJWo+WhT9BYM0Ji+… │      │
│                 │ 1dFpgJu8fF3LG0gl2ibSYiCi9a6hvU0TppjJyIWXh… │      │
│                 │ JDwRjW/656r0KVB02xHRKvm2ZKI03TglLIpmVCK3k… │      │
│                 │ x/9tpNFlQTl7B39rJlJWkR17QnZqVptFePFORoZmF… │      │
│                 │ -----END CERTIFICATE-----                  │      │
│                 │ -----BEGIN CERTIFICATE-----                │      │
│                 │ MIIFYjCCBEqgAwIBAgIQd70NbNs2+RrqIQ/E8FjTD… │      │
│                 │ MQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU… │      │
│                 │ CxMHUm9vdCBDQTEbMBkGA1UEAxMSR2xvYmFsU2lnb… │      │
│                 │ OTAwMDA0MloXDTI4MDEyODAwMDA0MlowRzELMAkGA… │      │
│                 │ GUdvb2dsZSBUcnVzdCBTZXJ2aWNlcyBMTEMxFDASB… │      │
│                 │ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCA… │      │
│                 │ ladAPKH9gvl9MgaCcfb2jH/76Nu8ai6Xl6OMS/kr9… │      │
│                 │ iV6nqlKr+CMny6SxnGPb15l+8Ape62im9MZaRw1NE… │      │
│                 │ KSUjB6G00j0uYODP0gmHu81I8E3CwnqIiru6z1kZ1… │      │
│                 │ DrXYfiYaRQM9sHmklCitD38m5agI/pboPGiUU+6DO… │      │
│                 │ j5ZPaK49l8KEj8C8QMALXL32h7M1bKwYUH+E4EzNk… │      │
│                 │ cuHKZPfmghCN6J3Cioj6OGaK/GP5Afl4/Xtcd/p2h… │      │
│                 │ CruOC7XFxYpVq9Os6pFLKcwZpDIlTirxZUTQAs6qz… │      │
│                 │ iYH6TKX/1Y7DzkvgtdizjkXPdsDtQCv9Uw+wp9U7D… │      │
│                 │ Eua++tgy/BBjFFFy3l3WFpO9KWgz7zpm7AeKJt8T1… │      │
│                 │ sZWwpbkNFhHax2xIPEDgfg1azVY80ZcFuctL7TlLn… │      │
│                 │ 9f6BQdgAmD06yK56mDcYBZUCAwEAAaOCATgwggE0M… │      │
│                 │ BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTkrysmc… │      │
│                 │ BgNVHSMEGDAWgBRge2YaRQ2XyolQL30EzTSo//z9S… │      │
│                 │ JQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnBraS5nb… │      │
│                 │ MAKGHWh0dHA6Ly9wa2kuZ29vZy9nc3IxL2dzcjEuY… │      │
│                 │ oCOGIWh0dHA6Ly9jcmwucGtpLmdvb2cvZ3NyMS9nc… │      │
│                 │ MAgGBmeBDAECATAIBgZngQwBAgIwDQYLKwYBBAHWe… │      │
│                 │ AwMwDQYJKoZIhvcNAQELBQADggEBADSkHrEoo9C0d… │      │
│                 │ NR3t5P+T4Vxfq7vqfM/b5A3Ri1fyJm9bvhdGaJQ3b… │      │
│                 │ WprKASOshIArAoyZl+tJaox118fessmXn1hIVw41o… │      │
│                 │ 9U5pCZEt4Wi4wStz6dTZ/CLANx8LZh1J7QJVj2fhM… │      │
│                 │ +qduBmpvvYuR7hZL6Dupszfnw0Skfths18dG9ZKb5… │      │
│                 │ d0lIKO2d1xozclOzgjXPYovJJIultzkMu34qQb9Sz… │      │
│                 │ -----END CERTIFICATE-----                  │      │
│                 │                                            │      │
│                 │ managed:                                   │      │
│                 │   domains:                                 │      │
│                 │     - "grucloud.org"                       │      │
│                 │   status: ACTIVE                           │      │
│                 │   domainStatus:                            │      │
│                 │     grucloud.org: ACTIVE                   │      │
│                 │ type: MANAGED                              │      │
│                 │ subjectAlternativeNames:                   │      │
│                 │   - "grucloud.org"                         │      │
│                 │ expireTime: 2021-09-28T03:48:42.000-07:00  │      │
│                 │ kind: compute#sslCertificate               │      │
│                 │                                            │      │
└─────────────────┴────────────────────────────────────────────┴──────┘


┌─────────────────────────────────────────────────────────────────────┐
│ 1 Bucket from google                                                │
├──────────────┬───────────────────────────────────────────────┬──────┤
│ Name         │ Data                                          │ Our  │
├──────────────┼───────────────────────────────────────────────┼──────┤
│ grucloud.org │ kind: storage#bucket                          │ Yes  │
│              │ selfLink: https://www.googleapis.com/storage… │      │
│              │ id: grucloud.org                              │      │
│              │ name: grucloud.org                            │      │
│              │ projectNumber: 91170824493                    │      │
│              │ metageneration: 2                             │      │
│              │ location: EUROPE-WEST4                        │      │
│              │ storageClass: STANDARD                        │      │
│              │ etag: CAI=                                    │      │
│              │ timeCreated: 2021-06-30T10:44:18.829Z         │      │
│              │ updated: 2021-06-30T10:44:19.640Z             │      │
│              │ website:                                      │      │
│              │   mainPageSuffix: index.html                  │      │
│              │   notFoundPage: 404.html                      │      │
│              │ labels:                                       │      │
│              │   managed-by: grucloud                        │      │
│              │   stage: dev                                  │      │
│              │ iamConfiguration:                             │      │
│              │   bucketPolicyOnly:                           │      │
│              │     enabled: true                             │      │
│              │     lockedTime: 2021-09-28T10:44:18.829Z      │      │
│              │   uniformBucketLevelAccess:                   │      │
│              │     enabled: true                             │      │
│              │     lockedTime: 2021-09-28T10:44:18.829Z      │      │
│              │   publicAccessPrevention: unspecified         │      │
│              │ locationType: region                          │      │
│              │ iam:                                          │      │
│              │   kind: storage#policy                        │      │
│              │   resourceId: projects/_/buckets/grucloud.org │      │
│              │   version: 1                                  │      │
│              │   etag: CAI=                                  │      │
│              │   bindings:                                   │      │
│              │     - role: roles/storage.legacyBucketOwner   │      │
│              │       members:                                │      │
│              │         - "projectEditor:grucloud-test"       │      │
│              │         - "projectOwner:grucloud-test"        │      │
│              │     - role: roles/storage.legacyBucketReader  │      │
│              │       members:                                │      │
│              │         - "projectViewer:grucloud-test"       │      │
│              │     - role: roles/storage.legacyObjectOwner   │      │
│              │       members:                                │      │
│              │         - "projectEditor:grucloud-test"       │      │
│              │         - "projectOwner:grucloud-test"        │      │
│              │     - role: roles/storage.legacyObjectReader  │      │
│              │       members:                                │      │
│              │         - "projectViewer:grucloud-test"       │      │
│              │     - role: roles/storage.objectViewer        │      │
│              │       members:                                │      │
│              │         - "allUsers"                          │      │
│              │                                               │      │
└──────────────┴───────────────────────────────────────────────┴──────┘


┌─────────────────────────────────────────────────────────────────────┐
│ 1 Object from google                                                │
├────────────┬─────────────────────────────────────────────────┬──────┤
│ Name       │ Data                                            │ Our  │
├────────────┼─────────────────────────────────────────────────┼──────┤
│ index.html │ kind: storage#object                            │ NO   │
│            │ id: grucloud.org/index.html/1625049860598468    │      │
│            │ selfLink: https://www.googleapis.com/storage/v… │      │
│            │ mediaLink: https://storage.googleapis.com/down… │      │
│            │ name: index.html                                │      │
│            │ bucket: grucloud.org                            │      │
│            │ generation: 1625049860598468                    │      │
│            │ metageneration: 1                               │      │
│            │ contentType: text/html                          │      │
│            │ storageClass: STANDARD                          │      │
│            │ size: 333                                       │      │
│            │ md5Hash: tVxlJ6kUMyBVNUg4XlUdJA==               │      │
│            │ crc32c: TISzGQ==                                │      │
│            │ etag: CMTVu72Wv/ECEAE=                          │      │
│            │ timeCreated: 2021-06-30T10:44:20.599Z           │      │
│            │ updated: 2021-06-30T10:44:20.599Z               │      │
│            │ timeStorageClassUpdated: 2021-06-30T10:44:20.5… │      │
│            │ metadata:                                       │      │
│            │   managed-by: grucloud                          │      │
│            │   stage: dev                                    │      │
│            │                                                 │      │
└────────────┴─────────────────────────────────────────────────┴──────┘


┌─────────────────────────────────────────────────────────────────────┐
│ 1 BackendBucket from google                                         │
├────────────────┬─────────────────────────────────────────────┬──────┤
│ Name           │ Data                                        │ Our  │
├────────────────┼─────────────────────────────────────────────┼──────┤
│ backend-bucket │ id: 8720064536531564011                     │ Yes  │
│                │ creationTimestamp: 2021-06-30T03:44:20.676… │      │
│                │ name: backend-bucket                        │      │
│                │ description: Managed By GruCloud            │      │
│                │ selfLink: https://www.googleapis.com/compu… │      │
│                │ bucketName: grucloud.org                    │      │
│                │ enableCdn: false                            │      │
│                │ kind: compute#backendBucket                 │      │
│                │                                             │      │
└────────────────┴─────────────────────────────────────────────┴──────┘


┌─────────────────────────────────────────────────────────────────────┐
│ 1 UrlMap from google                                                │
├──────────┬───────────────────────────────────────────────────┬──────┤
│ Name     │ Data                                              │ Our  │
├──────────┼───────────────────────────────────────────────────┼──────┤
│ url-map  │ id: 1187115894224057828                           │ Yes  │
│          │ creationTimestamp: 2021-06-30T03:44:27.793-07:00  │      │
│          │ name: url-map                                     │      │
│          │ description: Managed By GruCloud                  │      │
│          │ selfLink: https://www.googleapis.com/compute/v1/… │      │
│          │ defaultService: https://www.googleapis.com/compu… │      │
│          │ fingerprint: AFWyLkZ6QVA=                         │      │
│          │ kind: compute#urlMap                              │      │
│          │                                                   │      │
└──────────┴───────────────────────────────────────────────────┴──────┘


┌─────────────────────────────────────────────────────────────────────┐
│ 1 HttpsTargetProxy from google                                      │
├────────────────────┬─────────────────────────────────────────┬──────┤
│ Name               │ Data                                    │ Our  │
├────────────────────┼─────────────────────────────────────────┼──────┤
│ https-target-proxy │ id: 6271089959767242210                 │ Yes  │
│                    │ creationTimestamp: 2021-06-30T03:44:29… │      │
│                    │ name: https-target-proxy                │      │
│                    │ description: Managed By GruCloud        │      │
│                    │ selfLink: https://www.googleapis.com/c… │      │
│                    │ urlMap: https://www.googleapis.com/com… │      │
│                    │ c:                        │      │
│                    │   - "https://www.googleapis.com/comput… │      │
│                    │ fingerprint: _7WjZisemFI=               │      │
│                    │ kind: compute#targetHttpsProxy          │      │
│                    │                                         │      │
└────────────────────┴─────────────────────────────────────────┴──────┘


┌─────────────────────────────────────────────────────────────────────┐
│ 1 GlobalForwardingRule from google                                  │
├────────────────────────┬─────────────────────────────────────┬──────┤
│ Name                   │ Data                                │ Our  │
├────────────────────────┼─────────────────────────────────────┼──────┤
│ global-forwarding-rule │ id: 953550543260874208              │ Yes  │
│                        │ creationTimestamp: 2021-06-30T03:4… │      │
│                        │ name: global-forwarding-rule        │      │
│                        │ description: Managed By GruCloud    │      │
│                        │ IPAddress: 34.149.122.91            │      │
│                        │ IPProtocol: TCP                     │      │
│                        │ portRange: 443-443                  │      │
│                        │ target: https://www.googleapis.com… │      │
│                        │ selfLink: https://www.googleapis.c… │      │
│                        │ loadBalancingScheme: EXTERNAL       │      │
│                        │ networkTier: PREMIUM                │      │
│                        │ labelFingerprint: 42WmSpB8rSM=      │      │
│                        │ fingerprint: 3GGsVKhNuO4=           │      │
│                        │ kind: compute#forwardingRule        │      │
│                        │                                     │      │
└────────────────────────┴─────────────────────────────────────┴──────┘


List Summary:
Provider: google
┌────────────────────────────────────────────────────────────────────┐
│ google                                                             │
├────────────────────┬───────────────────────────────────────────────┤
│ SslCertificate     │ ssl-certificate                               │
├────────────────────┼───────────────────────────────────────────────┤
│ Bucket             │ grucloud.org                                  │
├────────────────────┼───────────────────────────────────────────────┤
│ Object             │ index.html                                    │
├────────────────────┼───────────────────────────────────────────────┤
│ BackendBucket      │ backend-bucket                                │
├────────────────────┼───────────────────────────────────────────────┤
│ UrlMap             │ url-map                                       │
├────────────────────┼───────────────────────────────────────────────┤
│ HttpsTargetProxy   │ https-target-proxy                            │
├────────────────────┼───────────────────────────────────────────────┤
│ GlobalForwardingR… │ global-forwarding-rule                        │
└────────────────────┴───────────────────────────────────────────────┘
7 resources, 7 types, 1 provider
Command "gc list" executed in 4s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update
&lt;/h3&gt;

&lt;p&gt;Let's deploy a new version of the website, in this very simple example, edit &lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/google/storage/website-https/websites/simple/index.html"&gt;website/simple/index.html&lt;/a&gt;, change something, and save the file.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;plan&lt;/em&gt; command helps to find out what is going to be deployed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc plan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Querying resources on 1 provider: google
✓ google
  ✓ Initialising
  ✓ Listing 7/7
  ✓ Querying
    ✓ Bucket 1/1
    ✓ Object 1/1
    ✓ SslCertificate 1/1
    ✓ BackendBucket 1/1
    ✓ UrlMap 1/1
    ✓ HttpsTargetProxy 1/1
    ✓ GlobalForwardingRule 1/1
┌───────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 1 Object from google                                                                                  │
├───────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐   │
│ │ UPDATE: name: index.html, id: grucloud.org/index.html/1625068113228566                          │   │
│ ├─────────────────────────────────────────────────────────────────────────────────────────────────┤   │
│ │ Key: md5                                                                                        │   │
│ ├────────────────────────────────────────────────┬────────────────────────────────────────────────┤   │
│ │ - nnLSNGP9RyK8uy7mni91nA==                     │ + tVxlJ6kUMyBVNUg4XlUdJA==                     │   │
│ └────────────────────────────────────────────────┴────────────────────────────────────────────────┘   │
└───────────────────────────────────────────────────────────────────────────────────────────────────────┘


┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Plan summary for provider google                                                               │
├────────────────────────────────────────────────────────────────────────────────────────────────┤
│ DEPLOY RESOURCES                                                                               │
├────────────────────┬───────────────────────────────────────────────────────────────────────────┤
│ Object             │ index.html                                                                │
└────────────────────┴───────────────────────────────────────────────────────────────────────────┘
1 resource to deploy on 1 provider
Command "gc p" executed in 4s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, &lt;em&gt;gc&lt;/em&gt; computes the MD5 hash of the file and compares it with the live version.&lt;br&gt;
Next, use the &lt;em&gt;apply&lt;/em&gt; command to effectively deploy.&lt;/p&gt;
&lt;h3&gt;
  
  
  Destroy
&lt;/h3&gt;

&lt;p&gt;Dispose of the infrastructure in the right order with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gc destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────────────────────┐
│ Destroy summary for provider google                                         │
├────────────────────┬────────────────────────────────────────────────────────┤
│ SslCertificate     │ ssl-certificate                                        │
├────────────────────┼────────────────────────────────────────────────────────┤
│ Bucket             │ grucloud.org                                           │
├────────────────────┼────────────────────────────────────────────────────────┤
│ BackendBucket      │ backend-bucket                                         │
├────────────────────┼────────────────────────────────────────────────────────┤
│ UrlMap             │ url-map                                                │
├────────────────────┼────────────────────────────────────────────────────────┤
│ HttpsTargetProxy   │ https-target-proxy                                     │
├────────────────────┼────────────────────────────────────────────────────────┤
│ GlobalForwardingR… │ global-forwarding-rule                                 │
└────────────────────┴────────────────────────────────────────────────────────┘
Destroying resources on 1 provider: google
✓ google
  ✓ Initialising
  ✓ Destroying
    ✓ SslCertificate 1/1
    ✓ Bucket 1/1
    ✓ BackendBucket 1/1
    ✓ UrlMap 1/1
    ✓ HttpsTargetProxy 1/1
    ✓ GlobalForwardingRule 1/1
  ✓ default::onDestroyed
    ✓ remove the load balancer A DNS record
6 resources destroyed, 6 types on 1 provider
Running OnDestroyedGlobal resources on 1 provider: google
Command "gc d -f" executed in 56s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/grucloud/grucloud"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com/docs/Introduction"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com"&gt;Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/grucloud_iac"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>googlecloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>Deploy, update, and destroy AWS EC2 Instance automatically</title>
      <dc:creator>Frederic</dc:creator>
      <pubDate>Fri, 30 Apr 2021 02:29:19 +0000</pubDate>
      <link>https://dev.to/fredericheem/deploy-update-and-destroy-aws-ec2-instance-automatically-1p0h</link>
      <guid>https://dev.to/fredericheem/deploy-update-and-destroy-aws-ec2-instance-automatically-1p0h</guid>
      <description>&lt;p&gt;This tutorial explains the deployment automation of a simple &lt;a href="https://aws.amazon.com/ec2/" rel="noopener noreferrer"&gt;AWS EC2 instance&lt;/a&gt; with the &lt;a href="https://www.npmjs.com/package/@grucloud/provider-aws" rel="noopener noreferrer"&gt;GruCloud AWS provider&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Instead of manually creating, updating, and destroying EC2 instances, the infrastructure will be described as Javascript code. The GruCloud CLI then reads this code, retrieves the lives resources through the AWS API, and decides what needs to be created, updated, or destroyed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Faws%2Fec2-simple%2Fdiagram-target.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Faws%2Fec2-simple%2Fdiagram-target.svg" alt="graph-diagram-ec2.svg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;h3&gt;
  
  
  AWS Account
&lt;/h3&gt;

&lt;p&gt;Ensure access to the &lt;a href="https://console.aws.amazon.com" rel="noopener noreferrer"&gt;Amazon Console&lt;/a&gt; and create an account if necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS CLI
&lt;/h3&gt;

&lt;p&gt;Ensure the &lt;em&gt;AWS CLI&lt;/em&gt; is installed and configured:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If not, visit &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Access and Secret Key
&lt;/h3&gt;

&lt;p&gt;Visit the &lt;a href="https://console.aws.amazon.com/iam/home#/security_credentials" rel="noopener noreferrer"&gt;security credentials&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on &lt;strong&gt;Access key (access key ID and secret access key).&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click on the button &lt;strong&gt;Create New Access Key&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Write down the &lt;strong&gt;AWSAccessKeyId&lt;/strong&gt; and &lt;strong&gt;AWSSecretKey&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In a further episode, the access and secret key will be obtained from a dedicated IAM user with the correct role and policy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Configure AWS CLI
&lt;/h3&gt;

&lt;p&gt;Configure the account with the previously obtained &lt;strong&gt;AWSAccessKeyId&lt;/strong&gt; and &lt;strong&gt;AWSSecretKey&lt;/strong&gt;, as well as the region, for instance &lt;code&gt;us-east-1&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws configure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Getting the GruCloud CLI
&lt;/h3&gt;

&lt;p&gt;GruCloud is written in Javascript running on &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;. Check if &lt;code&gt;node&lt;/code&gt; is present on your system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The version must be greater than 14&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Install the &lt;em&gt;GrucCloud&lt;/em&gt; command-line utility &lt;strong&gt;gc&lt;/strong&gt; with &lt;em&gt;npm&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; @grucloud/core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the current version of &lt;strong&gt;gc&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code Architecture
&lt;/h2&gt;

&lt;p&gt;In this section, we'll create the files needed to describe an infrastructure with GruCloud:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/aws/ec2-simple/package.json" rel="noopener noreferrer"&gt;package.json&lt;/a&gt;: specifies the npm dependencies and other information.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/aws/ec2-simple/config.js" rel="noopener noreferrer"&gt;config.js&lt;/a&gt;: the config function.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/aws/ec2-simple/iac.js" rel="noopener noreferrer"&gt;iac.js&lt;/a&gt;: exports &lt;em&gt;createStack&lt;/em&gt; with provider and resources associated&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/aws/ec2-simple/hook.js" rel="noopener noreferrer"&gt;hooks.js&lt;/a&gt;: optionally provides hook functions called after deployment or destruction.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;a href="https://github.com/grucloud/grucloud/tree/main/examples/aws/ec2-simple" rel="noopener noreferrer"&gt;source code&lt;/a&gt; for this example in on GitHub.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Create a new project
&lt;/h3&gt;

&lt;p&gt;Create a new directory, for instance &lt;code&gt;ec2-example&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;ec2-example
&lt;span class="nb"&gt;cd &lt;/span&gt;ec2-example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  package.json
&lt;/h3&gt;

&lt;p&gt;Let's create a new &lt;code&gt;package.json&lt;/code&gt; with the &lt;code&gt;npm init&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's install the GruCloud AWS provider called &lt;a href="https://www.npmjs.com/package/@grucloud/provider-aws" rel="noopener noreferrer"&gt;@grucloud/provider-aws&lt;/a&gt;, as well as the GruCloud core library &lt;code&gt;@grucloud/core&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @grucloud/core @grucloud/provider-aws
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  config.js
&lt;/h3&gt;

&lt;p&gt;The configuration is a Javascript function located in &lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/aws/ec2-simple/config.js" rel="noopener noreferrer"&gt;config.js&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pkg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./package.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;stage&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ec2Instance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;web-server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;InstanceType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;t2.micro&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;ImageId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ami-00f6a0c18edb19300&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Ubuntu 18.04&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will have to find out the &lt;code&gt;ImageId&lt;/code&gt; for your specific region. One way to retrieve to list of images is with the &lt;em&gt;aws cli&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 describe-images &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="s2"&gt;"Name=description,Values=Ubuntu Server 20.04 LTS"&lt;/span&gt; &lt;span class="s2"&gt;"Name=architecture,Values=x86_64"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This step will be automated in a future episode with the help of the &lt;a href="https://www.grucloud.com/docs/aws/resources/EC2/Image" rel="noopener noreferrer"&gt;Amazon Managed Image&lt;/a&gt; resource.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  iac.js
&lt;/h3&gt;

&lt;p&gt;Create a file called &lt;code&gt;iac.js&lt;/code&gt; which stands for &lt;em&gt;infrastructure as code&lt;/em&gt;.&lt;br&gt;
We'll first import &lt;em&gt;AwsProvider&lt;/em&gt; from &lt;a href="https://www.npmjs.com/package/@grucloud/provider-aws" rel="noopener noreferrer"&gt;@grucloud/provider-aws&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/aws/ec2-simple/iac.js" rel="noopener noreferrer"&gt;iac.js&lt;/a&gt; must export the &lt;code&gt;createStack&lt;/code&gt; function which returns the provider and the resources.&lt;/p&gt;

&lt;p&gt;Then, instantiate &lt;em&gt;AwsProvider&lt;/em&gt; by providing the &lt;em&gt;config&lt;/em&gt; function.&lt;/p&gt;

&lt;p&gt;In the case, an &lt;a href="https://www.grucloud.com/docs/aws/resources/EC2/EC2" rel="noopener noreferrer"&gt;EC2 Instance&lt;/a&gt; is defined with &lt;code&gt;provider.makeEC2&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// iac.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AwsProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@grucloud/provider-aws&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createStack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;stage&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AwsProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./config&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;stage&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ec2Instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeEC2&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ec2Instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ec2Instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ec2Instance&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  GruCloud CLI
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Info
&lt;/h3&gt;

&lt;p&gt;As a way to verify that &lt;strong&gt;gc&lt;/strong&gt; can connect to the AWS API, one can use the &lt;code&gt;info&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  - provider:
      name: aws
      type: aws
    stage: dev
    accountId: 840541460064
    zone: eu-west-2a
    config:
      projectName: ec2-simple
      ec2Instance:
        name: web-server
        properties:
          InstanceType: t2.micro
          ImageId: ami-00f6a0c18edb19300
      stage: dev
      zone: [object Function]
      accountId: [object Function]
      region: eu-west-2

Command "gc info" executed in 1s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploy
&lt;/h3&gt;

&lt;p&gt;We are ready to deploy with &lt;code&gt;apply&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Querying resources on 1 provider: aws
✓ aws
  ✓ Initialising
  ✓ Listing 6/6
  ✓ Querying
    ✓ EC2 1/1
┌──────────────────────────────────────────────────────────────────────────┐
│ 1 EC2 from aws                                                           │
├────────────┬──────────┬──────────────────────────────────────────────────┤
│ Name       │ Action   │ Data                                             │
├────────────┼──────────┼──────────────────────────────────────────────────┤
│ web-server │ CREATE   │ InstanceType: t2.micro                           │
│            │          │ ImageId: ami-00f6a0c18edb19300                   │
│            │          │ MaxCount: 1                                      │
│            │          │ MinCount: 1                                      │
│            │          │ TagSpecifications:                               │
│            │          │   - ResourceType: instance                       │
│            │          │     Tags:                                        │
│            │          │       - Key: Name                                │
│            │          │         Value: web-server                        │
│            │          │       - Key: ManagedBy                           │
│            │          │         Value: GruCloud                          │
│            │          │       - Key: CreatedByProvider                   │
│            │          │         Value: aws                               │
│            │          │       - Key: stage                               │
│            │          │         Value: dev                               │
│            │          │       - Key: projectName                         │
│            │          │         Value: ec2-simple                        │
│            │          │                                                  │
└────────────┴──────────┴──────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────────┐
│ Plan summary for provider aws                                           │
├─────────────────────────────────────────────────────────────────────────┤
│ DEPLOY RESOURCES                                                        │
├────────────────────┬────────────────────────────────────────────────────┤
│ EC2                │ web-server                                         │
└────────────────────┴────────────────────────────────────────────────────┘
? Are you sure to deploy 1 resource, 1 type on 1 provider? › (y/N)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, you are given the opportunity to look at what is going to be deployed.&lt;br&gt;
Type &lt;code&gt;y&lt;/code&gt; to accept:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Deploying resources on 1 provider: aws
✓ aws
  ✓ Initialising
  ✓ Deploying
    ✓ EC2 1/1
1 resource deployed of 1 type and 1 provider
Running OnDeployedGlobal resources on 1 provider: aws
Command "gc a" executed in 1m 29s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;gc apply&lt;/code&gt; is executed a second time, resources should not be created or destroyed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Querying resources on 1 provider: aws
✓ aws
  ✓ Initialising
  ✓ Listing 13/13
  ✓ Querying
    ✓ EC2 1/1
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│ Plan summary for provider aws                                                           │
└─────────────────────────────────────────────────────────────────────────────────────────┘
Nothing to deploy
Running OnDeployedGlobal resources on 1 provider: aws
Command "gc a" executed in 9s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As expected, nothing to deploy, the target resources defined in the code match the live resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  List
&lt;/h3&gt;

&lt;p&gt;To list all the resources, and generate a diagram:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gc list --graph --all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will include the default AWS resources such as VPC, subnet, internet gateway, and security group.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Faws%2Fec2-simple%2Fdiagram-live.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Faws%2Fec2-simple%2Fdiagram-live.svg" alt="graph-live"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To list only the resources created by GruCloud:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gc list --our
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Listing resources on 1 provider: aws
✓ aws
  ✓ Initialising
  ✓ Listing 13/13
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 1 EC2 from aws                                                                                          │
├────────────┬─────────────────────────────────────────────────────────────────────────────────────┬──────┤
│ Name       │ Data                                                                                │ Our  │
├────────────┼─────────────────────────────────────────────────────────────────────────────────────┼──────┤
│ web-server │ AmiLaunchIndex: 0                                                                   │ Yes  │
│            │ ImageId: ami-00f6a0c18edb19300                                                      │      │
│            │ InstanceId: i-016628a1b6a6a2f91                                                     │      │
│            │ InstanceType: t3.micro                                                              │      │
│            │ LaunchTime: 2021-04-29T23:10:44.000Z                                                │      │
│            │ Monitoring:                                                                         │      │
│            │   State: disabled                                                                   │      │
│            │ Placement:                                                                          │      │
│            │   AvailabilityZone: eu-west-2a                                                      │      │
│            │   GroupName:                                                                        │      │
│            │   Tenancy: default                                                                  │      │
│            │ PrivateDnsName: ip-172-31-2-146.eu-west-2.compute.internal                          │      │
│            │ PrivateIpAddress: 172.31.2.146                                                      │      │
│            │ ProductCodes: []                                                                    │      │
│            │ PublicDnsName: ec2-18-132-98-216.eu-west-2.compute.amazonaws.com                    │      │
│            │ PublicIpAddress: 18.132.98.216                                                      │      │
│            │ State:                                                                              │      │
│            │   Code: 16                                                                          │      │
│            │   Name: running                                                                     │      │
│            │ StateTransitionReason:                                                              │      │
│            │ SubnetId: subnet-0f6f085fc384bf8ce                                                  │      │
│            │ VpcId: vpc-bbbafcd3                                                                 │      │
│            │ Architecture: x86_64                                                                │      │
│            │ BlockDeviceMappings:                                                                │      │
│            │   - DeviceName: /dev/sda1                                                           │      │
│            │     Ebs:                                                                            │      │
│            │       AttachTime: 2021-04-29T23:10:45.000Z                                          │      │
│            │       DeleteOnTermination: true                                                     │      │
│            │       Status: attached                                                              │      │
│            │       VolumeId: vol-0a88a34248fe18740                                               │      │
│            │ ClientToken: 7ef5fd60-e962-400f-a2b9-37719d8329ed                                   │      │
│            │ EbsOptimized: false                                                                 │      │
│            │ EnaSupport: true                                                                    │      │
│            │ Hypervisor: xen                                                                     │      │
│            │ ElasticGpuAssociations: []                                                          │      │
│            │ ElasticInferenceAcceleratorAssociations: []                                         │      │
│            │ NetworkInterfaces:                                                                  │      │
│            │   - Association:                                                                    │      │
│            │       IpOwnerId: amazon                                                             │      │
│            │       PublicDnsName: ec2-18-132-98-216.eu-west-2.compute.amazonaws.com              │      │
│            │       PublicIp: 18.132.98.216                                                       │      │
│            │     Attachment:                                                                     │      │
│            │       AttachTime: 2021-04-29T23:10:44.000Z                                          │      │
│            │       AttachmentId: eni-attach-02744addcff43ecbb                                    │      │
│            │       DeleteOnTermination: true                                                     │      │
│            │       DeviceIndex: 0                                                                │      │
│            │       Status: attached                                                              │      │
│            │       NetworkCardIndex: 0                                                           │      │
│            │     Description:                                                                    │      │
│            │     Groups:                                                                         │      │
│            │       - GroupName: default                                                          │      │
│            │         GroupId: sg-f4139a96                                                        │      │
│            │     Ipv6Addresses: []                                                               │      │
│            │     MacAddress: 06:ee:ef:d7:1c:48                                                   │      │
│            │     NetworkInterfaceId: eni-06e9d87ff776cf40f                                       │      │
│            │     OwnerId: 840541460064                                                           │      │
│            │     PrivateDnsName: ip-172-31-2-146.eu-west-2.compute.internal                      │      │
│            │     PrivateIpAddress: 172.31.2.146                                                  │      │
│            │     PrivateIpAddresses:                                                             │      │
│            │       - Association:                                                                │      │
│            │           IpOwnerId: amazon                                                         │      │
│            │           PublicDnsName: ec2-18-132-98-216.eu-west-2.compute.amazonaws.com          │      │
│            │           PublicIp: 18.132.98.216                                                   │      │
│            │         Primary: true                                                               │      │
│            │         PrivateDnsName: ip-172-31-2-146.eu-west-2.compute.internal                  │      │
│            │         PrivateIpAddress: 172.31.2.146                                              │      │
│            │     SourceDestCheck: true                                                           │      │
│            │     Status: in-use                                                                  │      │
│            │     SubnetId: subnet-0f6f085fc384bf8ce                                              │      │
│            │     VpcId: vpc-bbbafcd3                                                             │      │
│            │     InterfaceType: interface                                                        │      │
│            │ RootDeviceName: /dev/sda1                                                           │      │
│            │ RootDeviceType: ebs                                                                 │      │
│            │ SecurityGroups:                                                                     │      │
│            │   - GroupName: default                                                              │      │
│            │     GroupId: sg-f4139a96                                                            │      │
│            │ SourceDestCheck: true                                                               │      │
│            │ Tags:                                                                               │      │
│            │   - Key: Name                                                                       │      │
│            │     Value: web-server                                                               │      │
│            │   - Key: stage                                                                      │      │
│            │     Value: dev                                                                      │      │
│            │   - Key: CreatedByProvider                                                          │      │
│            │     Value: aws                                                                      │      │
│            │   - Key: ManagedBy                                                                  │      │
│            │     Value: GruCloud                                                                 │      │
│            │   - Key: projectName                                                                │      │
│            │     Value: ec2-simple                                                               │      │
│            │ VirtualizationType: hvm                                                             │      │
│            │ CpuOptions:                                                                         │      │
│            │   CoreCount: 1                                                                      │      │
│            │   ThreadsPerCore: 2                                                                 │      │
│            │ CapacityReservationSpecification:                                                   │      │
│            │   CapacityReservationPreference: open                                               │      │
│            │ HibernationOptions:                                                                 │      │
│            │   Configured: false                                                                 │      │
│            │ Licenses: []                                                                        │      │
│            │ MetadataOptions:                                                                    │      │
│            │   State: applied                                                                    │      │
│            │   HttpTokens: optional                                                              │      │
│            │   HttpPutResponseHopLimit: 1                                                        │      │
│            │   HttpEndpoint: enabled                                                             │      │
│            │ EnclaveOptions:                                                                     │      │
│            │   Enabled: false                                                                    │      │
│            │                                                                                     │      │
└────────────┴─────────────────────────────────────────────────────────────────────────────────────┴──────┘


List Summary:
Provider: aws
┌────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ aws                                                                                                    │
├────────────────────┬───────────────────────────────────────────────────────────────────────────────────┤
│ EC2                │ web-server                                                                        │
└────────────────────┴───────────────────────────────────────────────────────────────────────────────────┘
1 resource, 7 types, 1 provider
Command "gc l -o" executed in 7s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note that tags have been added to the EC2 Instance, it gives GruCloud a way to identify the resources under its control. Unlike other infrastructure as code tools such as Terraform and Pulumi, GruCloud does not need a &lt;em&gt;state&lt;/em&gt; file. Hence removing a lot of complexity and issues.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Update
&lt;/h3&gt;

&lt;p&gt;The ec2 instance configuration might change, for instance, let's modify the machine type to &lt;code&gt;t3.micro&lt;/code&gt; located in &lt;em&gt;config.js&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;plan&lt;/code&gt; command is a read-only command which fetches the live resources and compares them with the target resources defined in the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc plan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Querying resources on 1 provider: aws
✓ aws
  ✓ Initialising
  ✓ Listing 13/13
  ✓ Querying
    ✓ EC2 1/1
┌──────────────────────────────────────────────────────────────────────────────────────────┐
│ 1 EC2 from aws                                                                           │
├────────────┬──────────┬──────────────────────────────────────────────────────────────────┤
│ Name       │ Action   │ Data                                                             │
├────────────┼──────────┼──────────────────────────────────────────────────────────────────┤
│ web-server │ UPDATE   │ added:                                                           │
│            │          │ updated:                                                         │
│            │          │   InstanceType: t3.micro                                         │
│            │          │                                                                  │
└────────────┴──────────┴──────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────────────────┐
│ Plan summary for provider aws                                                           │
├─────────────────────────────────────────────────────────────────────────────────────────┤
│ DEPLOY RESOURCES                                                                        │
├────────────────────┬────────────────────────────────────────────────────────────────────┤
│ EC2                │ web-server                                                         │
└────────────────────┴────────────────────────────────────────────────────────────────────┘
1 resource to deploy on 1 provider
Command "gc plan" executed in 5s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's apply the change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Bear in mind that the machine requires to be stopped and restarted.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Trust but verify, hence, list the EC2 instances and check the &lt;code&gt;InstanceType&lt;/code&gt; has been changed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc l &lt;span class="nt"&gt;-t&lt;/span&gt; EC2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Output
&lt;/h3&gt;

&lt;p&gt;Another useful command is &lt;em&gt;gc output&lt;/em&gt;, which extract information for a specific field of a given resource&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gc output -t EC2 --name web-server -f InstanceType
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;t3.micro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nested field can be accessed too, for example, let's retrieve the public IP address attached to the EC2 instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc output &lt;span class="nt"&gt;-t&lt;/span&gt; EC2 &lt;span class="nt"&gt;--name&lt;/span&gt; web-server &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s1"&gt;'NetworkInterfaces[0].Association.PublicIp'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;18.130.34.212
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The temptation to ping is high:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ping &lt;span class="sb"&gt;`&lt;/span&gt;gc output &lt;span class="nt"&gt;-t&lt;/span&gt; EC2 &lt;span class="nt"&gt;--name&lt;/span&gt; web-server &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s1"&gt;'NetworkInterfaces[0].Association.PublicIp'&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PING 18.130.34.212 (18.130.34.212): 56 data bytes
64 bytes from 18.130.34.212: icmp_seq=0 ttl=38 time=153.799 ms
64 bytes from 18.130.34.212: icmp_seq=1 ttl=38 time=153.583 ms
64 bytes from 18.130.34.212: icmp_seq=2 ttl=38 time=140.622 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Destroy
&lt;/h3&gt;

&lt;p&gt;Time to destroy the resources allocated and therefore save a lot of £$€.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Find Deletable resources on 1 provider: aws
✓ aws
  ✓ Initialising
  ✓ Listing 6/6
? Are you sure to destroy 1 resource, 1 type on 1 provider? › (y/N)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once again, you are given the opportunity to look at what is going to be destroyed.&lt;br&gt;
Type 'y' to confirm the destruction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Destroying resources on 1 provider: aws
✓ aws
  ✓ Initialising
  ✓ Destroying
    ✓ EC2 1/1
1 resource destroyed, 1 type on 1 provider
Running OnDestroyedGlobal resources on 1 provider: aws
Command "gc destroy" executed in 1m 29s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's run the &lt;code&gt;gc list&lt;/code&gt; command with the &lt;code&gt;E2&lt;/code&gt; filter to verify the EC2 is gone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gc l -t EC2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Listing resources on 1 provider: aws
✓ aws
  ✓ Initialising
  ✓ Listing 6/6
List Summary:
Provider: aws
┌─────────────────────────────────────────────────────────────────────────┐
│ aws                                                                     │
└─────────────────────────────────────────────────────────────────────────┘
0 resources, 0 types, 1 provider
Command "gc list -t EC2" executed in 3s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example demonstrates how to code a very basic infrastructure with one EC2 instance, and how can we use the &lt;code&gt;gc apply&lt;/code&gt;, &lt;code&gt;gc list&lt;/code&gt;, &lt;code&gt;gc destroy&lt;/code&gt; and &lt;code&gt;gc graph&lt;/code&gt; to manage the infrastructure.&lt;/p&gt;

&lt;p&gt;It paves the way for more &lt;a href="https://www.grucloud.com/docs/aws/AwsExamples" rel="noopener noreferrer"&gt;AWS examples&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Graph
&lt;/h3&gt;

&lt;p&gt;A picture is worth a thousand words, GruCloud generates an SVG file describing the resources and their relationship.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gc graph
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the graph of a typical web application managed by Kubernetes running on AWS where the master node is managed by EKS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Fstarhackit%2Feks-lean%2Fdiagram-target.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Fstarhackit%2Feks-lean%2Fdiagram-target.svg" alt="kubernetes eks"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/grucloud/grucloud" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com/docs/Introduction" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/grucloud_iac" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>ec2</category>
      <category>iac</category>
      <category>automation</category>
    </item>
    <item>
      <title>Kubernetes defined as Javascript Code with GruCloud  </title>
      <dc:creator>Frederic</dc:creator>
      <pubDate>Wed, 28 Apr 2021 23:11:22 +0000</pubDate>
      <link>https://dev.to/fredericheem/kubernetes-defined-as-javascript-code-with-grucloud-422p</link>
      <guid>https://dev.to/fredericheem/kubernetes-defined-as-javascript-code-with-grucloud-422p</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The Kubernetes Grucloud provider allows to define and describe Kubernetes manifests in Javascript, removing the need to write YAML or template files.&lt;/p&gt;

&lt;p&gt;The GruCloud Command Line Interface &lt;strong&gt;gc&lt;/strong&gt; reads a description in Javascript and connects to the k8s control plane to apply the new or updated resource definitions.&lt;/p&gt;

&lt;p&gt;For this tutorial, we will define a &lt;a href="https://www.grucloud.com/docs/k8s/resources/Namespace" rel="noopener noreferrer"&gt;Namespace&lt;/a&gt;, a &lt;a href="https://www.grucloud.com/docs/k8s/resources/Service" rel="noopener noreferrer"&gt;Service&lt;/a&gt;, and a &lt;a href="https://www.grucloud.com/docs/k8s/resources/Deployment" rel="noopener noreferrer"&gt;Deployment&lt;/a&gt; to deploy an Nginx web server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Fk8s%2Ftuto1%2Fdiagram-target.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Fk8s%2Ftuto1%2Fdiagram-target.svg" alt="diagram-target"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This diagram is generated from the code with &lt;code&gt;gc graph&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;Ensure &lt;strong&gt;kubectl&lt;/strong&gt; is installed, and &lt;strong&gt;minikube&lt;/strong&gt; is started: &lt;a href="//./K8sRequirements.md"&gt;K8s Requirements&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is always a good idea to verify the current &lt;em&gt;kubectl&lt;/em&gt; context, especially when switching k8s clusters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl config current-context
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Getting GruCloud CLI: gc
&lt;/h3&gt;

&lt;p&gt;The GruCloud CLI, &lt;code&gt;gc&lt;/code&gt;, is written in Javascript and run on &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;, hence &lt;em&gt;node&lt;/em&gt; is required:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install &lt;code&gt;gc&lt;/code&gt; in just one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; @grucloud/core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify &lt;em&gt;gc&lt;/em&gt; is installed properly by displaying the version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gc --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Project Content
&lt;/h2&gt;

&lt;p&gt;We'll describe in the next sections the 4 files required for this &lt;em&gt;infrastructure as code&lt;/em&gt; project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/k8s/tuto1/package.json" rel="noopener noreferrer"&gt;package.json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/k8s/tuto1/config.js" rel="noopener noreferrer"&gt;config.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/k8s/tuto1/iac.js" rel="noopener noreferrer"&gt;iac.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/k8s/tuto1/hook.js" rel="noopener noreferrer"&gt;hook.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The link to the &lt;a href="https://github.com/grucloud/grucloud/tree/main/examples/k8s/tuto1" rel="noopener noreferrer"&gt;source code for this tutorial&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's create a new project directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;tuto
&lt;span class="nb"&gt;cd &lt;/span&gt;tuto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  package.json
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;npm init&lt;/code&gt; command will create a basic &lt;em&gt;package.json&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's install the &lt;a href="https://www.npmjs.com/package/@grucloud/provider-k8s" rel="noopener noreferrer"&gt;GruCloud Kubernetes provider&lt;/a&gt; and the SDK. We'll also install &lt;a href="https://github.com/axios/axios" rel="noopener noreferrer"&gt;axios&lt;/a&gt; and &lt;a href="https://rubico.land/" rel="noopener noreferrer"&gt;rubico&lt;/a&gt;, needed for the post-deployment hooks, which does some final health check.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @grucloud/core @grucloud/provider-k8s rubico axios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  config.js
&lt;/h3&gt;

&lt;p&gt;Create the &lt;strong&gt;config.js&lt;/strong&gt; which contains the configuration for this project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pkg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./package.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;myapp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;appLabel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nginx-label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nginx-service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;deployment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nginx-deployment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nginx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nginx:1.14.2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  iac.js
&lt;/h3&gt;

&lt;p&gt;Let's create the &lt;em&gt;iac.js&lt;/em&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// iac.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;K8sProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@grucloud/provider-k8s&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Create a namespace, service and deployment&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeNamespace&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeService&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;NodePort&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TCP&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;nodePort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30020&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deployment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeDeployment&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
              &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                  &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;],&lt;/span&gt;
              &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;deployment&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createStack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;K8sProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createResource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./hook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  hook.js
&lt;/h3&gt;

&lt;p&gt;When the resources are created, any code can be invoked, defined in &lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/k8s/tuto1/hook.js" rel="noopener noreferrer"&gt;hook.js&lt;/a&gt;, useful to perform some final health check.&lt;/p&gt;

&lt;p&gt;In this case, the &lt;em&gt;kubectl port-forward&lt;/em&gt; is called with the right option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl --namespace myapp port-forward svc/nginx-service 8081:80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we'll use the &lt;em&gt;axios&lt;/em&gt; library to perform HTTP calls to the web server, retrying if necessary.&lt;/p&gt;

&lt;p&gt;When the website is up, it will open a browser at &lt;a href="http://localhost:8081" rel="noopener noreferrer"&gt;http://localhost:8081&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// hook.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;assert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;assert&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rubico&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rubico/x&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;retryCallOnError&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@grucloud/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Retry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shelljs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;localPort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8081&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;localPort&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;servicePort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;({}),&lt;/span&gt;
    &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spec.ports&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;port&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;])();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kubectlPortForwardCommand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`kubectl --namespace &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; port-forward svc/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;localPort&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;servicePort&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="nx"&gt;e3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;withCredentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;onDeployed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;init&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
      &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`exec: '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;kubectlPortForwardCommand&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;', check web server at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// start kubectl port-forward&lt;/span&gt;
            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;child&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;kubectlPortForwardCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;async&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;

            &lt;span class="c1"&gt;// Get the web page, retry until it succeeds&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;retryCallOnError&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
              &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`get &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="na"&gt;shouldRetryOnException&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
                &lt;span class="nf"&gt;or&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                  &lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;code&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ECONNREFUSED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                  &lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;response.status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="p"&gt;])(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="na"&gt;isExpectedResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s2"&gt;`text/html`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
              &lt;span class="p"&gt;},&lt;/span&gt;
              &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;retryCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;retryDelay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;e3&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="c1"&gt;// Open a browser&lt;/span&gt;
            &lt;span class="nx"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`open &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;async&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;onDestroyed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;init&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Workflow
&lt;/h2&gt;

&lt;p&gt;We'll describe the most useful &lt;em&gt;gc&lt;/em&gt; commands: &lt;code&gt;apply&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;destroy&lt;/code&gt;, and &lt;code&gt;plan&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy
&lt;/h3&gt;

&lt;p&gt;We are now ready to deploy the resources with the &lt;a href="https://www.grucloud.com/docs/cli/PlanApply" rel="noopener noreferrer"&gt;apply&lt;/a&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first part is to find out the plan, i.e what is going to be deployed.&lt;br&gt;
You will be prompted if you accept or abort.&lt;br&gt;
When typing: 'y', the resources will be deployed: a namespace, a service, and a deployment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Querying resources on 1 provider: k8s
✓ k8s
  ✓ Initialising
  ✓ Listing 7/7
  ✓ Querying
    ✓ Namespace 1/1
    ✓ Service 1/1
    ✓ Deployment 1/1
┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 1 Namespace from k8s                                                                                 │
├──────────┬──────────┬────────────────────────────────────────────────────────────────────────────────┤
│ Name     │ Action   │ Data                                                                           │
├──────────┼──────────┼────────────────────────────────────────────────────────────────────────────────┤
│ myapp    │ CREATE   │ apiVersion: v1                                                                 │
│          │          │ kind: Namespace                                                                │
│          │          │ metadata:                                                                      │
│          │          │   name: myapp                                                                  │
│          │          │   annotations:                                                                 │
│          │          │     Name: myapp                                                                │
│          │          │     ManagedBy: GruCloud                                                        │
│          │          │     CreatedByProvider: k8s                                                     │
│          │          │     stage: dev                                                                 │
│          │          │     projectName: @grucloud/example-k8s-tuto1                                   │
│          │          │                                                                                │
└──────────┴──────────┴────────────────────────────────────────────────────────────────────────────────┘


┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 1 Service from k8s                                                                                   │
├──────────────────────┬──────────┬────────────────────────────────────────────────────────────────────┤
│ Name                 │ Action   │ Data                                                               │
├──────────────────────┼──────────┼────────────────────────────────────────────────────────────────────┤
│ myapp::nginx-service │ CREATE   │ spec:                                                              │
│                      │          │   selector:                                                        │
│                      │          │     app: nginx-label                                               │
│                      │          │   type: NodePort                                                   │
│                      │          │   ports:                                                           │
│                      │          │     - protocol: TCP                                                │
│                      │          │       port: 80                                                     │
│                      │          │       targetPort: 8080                                             │
│                      │          │ apiVersion: v1                                                     │
│                      │          │ kind: Service                                                      │
│                      │          │ metadata:                                                          │
│                      │          │   name: nginx-service                                              │
│                      │          │   annotations:                                                     │
│                      │          │     Name: nginx-service                                            │
│                      │          │     ManagedBy: GruCloud                                            │
│                      │          │     CreatedByProvider: k8s                                         │
│                      │          │     stage: dev                                                     │
│                      │          │     projectName: @grucloud/example-k8s-tuto1                       │
│                      │          │   namespace: myapp                                                 │
│                      │          │                                                                    │
└──────────────────────┴──────────┴────────────────────────────────────────────────────────────────────┘


┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 1 Deployment from k8s                                                                                │
├─────────────────────────┬──────────┬─────────────────────────────────────────────────────────────────┤
│ Name                    │ Action   │ Data                                                            │
├─────────────────────────┼──────────┼─────────────────────────────────────────────────────────────────┤
│ myapp::nginx-deployment │ CREATE   │ metadata:                                                       │
│                         │          │   labels:                                                       │
│                         │          │     app: nginx-label                                            │
│                         │          │   name: nginx-deployment                                        │
│                         │          │   annotations:                                                  │
│                         │          │     Name: nginx-deployment                                      │
│                         │          │     ManagedBy: GruCloud                                         │
│                         │          │     CreatedByProvider: k8s                                      │
│                         │          │     stage: dev                                                  │
│                         │          │     projectName: @grucloud/example-k8s-tuto1                    │
│                         │          │   namespace: myapp                                              │
│                         │          │ spec:                                                           │
│                         │          │   replicas: 1                                                   │
│                         │          │   selector:                                                     │
│                         │          │     matchLabels:                                                │
│                         │          │       app: nginx-label                                          │
│                         │          │   template:                                                     │
│                         │          │     metadata:                                                   │
│                         │          │       labels:                                                   │
│                         │          │         app: nginx-label                                        │
│                         │          │     spec:                                                       │
│                         │          │       containers:                                               │
│                         │          │         - name: nginx                                           │
│                         │          │           image: nginx:1.14.2                                   │
│                         │          │           ports:                                                │
│                         │          │             - containerPort: 80                                 │
│                         │          │ apiVersion: apps/v1                                             │
│                         │          │ kind: Deployment                                                │
│                         │          │                                                                 │
└─────────────────────────┴──────────┴─────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Plan summary for provider k8s                                                                       │
├─────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ DEPLOY RESOURCES                                                                                    │
├────────────────────┬────────────────────────────────────────────────────────────────────────────────┤
│ Namespace          │ myapp                                                                          │
├────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ Service            │ myapp::nginx-service                                                           │
├────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ Deployment         │ myapp::nginx-deployment                                                        │
└────────────────────┴────────────────────────────────────────────────────────────────────────────────┘
✔ Are you sure to deploy 3 resources, 3 types on 1 provider? … yes
Deploying resources on 1 provider: k8s
✓ k8s
  ✓ Initialising
  ✓ Deploying
    ✓ Namespace 1/1
    ✓ Service 1/1
    ✓ Deployment 1/1
3 resources deployed of 3 types and 1 provider
Running OnDeployedGlobal resources on 1 provider: k8s
Command "gc a" executed in 30s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the case of the &lt;code&gt;Deployment&lt;/code&gt; type manifest, &lt;strong&gt;gc&lt;/strong&gt; will query the pod that is started by the deployment through the replica set, when one of the container's pod is ready, the deployment can proceed.&lt;/p&gt;

&lt;p&gt;Later on, when we deal with the &lt;code&gt;Ingress&lt;/code&gt; type, &lt;strong&gt;gc&lt;/strong&gt; will wait for the load balancer to be ready.&lt;/p&gt;

&lt;p&gt;The command &lt;code&gt;gc apply&lt;/code&gt; is the equivalent of &lt;code&gt;kubectl apply -f mymanifest.yaml&lt;/code&gt; but it waits for resources to be up and running, ready to serve.&lt;/p&gt;

&lt;p&gt;We could try to run the &lt;code&gt;gc apply&lt;/code&gt; or the &lt;code&gt;gc plan&lt;/code&gt;, we should not expect any deployment or destruction of resources.&lt;/p&gt;

&lt;p&gt;In the mathematical and computer science world, we could say that &lt;em&gt;apply&lt;/em&gt; (and &lt;em&gt;destroy&lt;/em&gt;) commands are &lt;a href="https://en.wikipedia.org/wiki/Idempotence" rel="noopener noreferrer"&gt;idempotent&lt;/a&gt;: "property of certain operations in mathematics and computer science whereby they can be applied multiple times without changing the result beyond the initial application".&lt;/p&gt;

&lt;h3&gt;
  
  
  List
&lt;/h3&gt;

&lt;p&gt;Let's verify that the resources are deployed with the &lt;em&gt;gc list&lt;/em&gt; command:&lt;/p&gt;

&lt;p&gt;A live diagram will be also generated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc list &lt;span class="nt"&gt;--our&lt;/span&gt; &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List Summary:
Provider: k8s
┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ k8s                                                                                                 │
├────────────────────┬────────────────────────────────────────────────────────────────────────────────┤
│ Namespace          │ myapp                                                                          │
├────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ Service            │ myapp::nginx-service                                                           │
├────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ Deployment         │ myapp::nginx-deployment                                                        │
├────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ ReplicaSet         │ myapp::nginx-deployment-66cdc8d56b                                             │
├────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ Pod                │ myapp::nginx-deployment-66cdc8d56b-4d8lz                                       │
└────────────────────┴────────────────────────────────────────────────────────────────────────────────┘
5 resources, 15 types, 1 provider
Command "gc list --our --all --graph" executed in 0s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Fk8s%2Ftuto1%2Fdiagram-live.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgrucloud%2Fgrucloud%2Fmain%2Fexamples%2Fk8s%2Ftuto1%2Fdiagram-live.svg" alt="diagram-live"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice the relationship between the Pod, ReplicaSet and Deployment.&lt;/p&gt;

&lt;p&gt;The Deployment creates a ReplicaSet which creates a one or more Pod(s).&lt;/p&gt;

&lt;p&gt;When querying the &lt;em&gt;k8s-api-server&lt;/em&gt; for the live resources, the pod contains information about its ReplicaSet parent, who has itself information about its parent Deployment. This allows &lt;em&gt;gc&lt;/em&gt; to find out the links between the resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  Post Deploy Hook
&lt;/h3&gt;

&lt;p&gt;Would like to check the health of the system? You can run the &lt;em&gt;onDeployed&lt;/em&gt; hook any time with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc run &lt;span class="nt"&gt;--onDeployed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Running OnDeployed resources on 1 provider: k8s
Forwarding from 127.0.0.1:8081 -&amp;gt; 80
Forwarding from [::1]:8081 -&amp;gt; 80
Handling connection for 8081
✓ k8s
  ✓ Initialising
  ✓ default::onDeployed
    ✓ exec: 'kubectl --namespace myapp port-forward svc/nginx-service 8081:80', check web server at http://localhost:8081
Command "gc run --onDeployed" executed in 5s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update
&lt;/h3&gt;

&lt;p&gt;Now that the initial deployment is successful, some changes will be made, for instance, let's change the Nginx container version, located at &lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/k8s/tuto1/config.js" rel="noopener noreferrer"&gt;config.js&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Browse the list of Nginx images at &lt;a href="https://hub.docker.com/_/nginx" rel="noopener noreferrer"&gt;https://hub.docker.com/_/nginx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's try the version &lt;code&gt;nginx:1.20.0-alpine&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For a preview of the change that will be made, use the &lt;em&gt;plan&lt;/em&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc plan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Querying resources on 1 provider: k8s
✓ k8s
  ✓ Initialising
  ✓ Listing 7/7
  ✓ Querying
    ✓ Namespace 1/1
    ✓ Service 1/1
    ✓ Deployment 1/1
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 1 Deployment from k8s                                                                                             │
├─────────────────────────┬──────────┬──────────────────────────────────────────────────────────────────────────────┤
│ Name                    │ Action   │ Data                                                                         │
├─────────────────────────┼──────────┼──────────────────────────────────────────────────────────────────────────────┤
│ myapp::nginx-deployment │ UPDATE   │ added:                                                                       │
│                         │          │ deleted:                                                                     │
│                         │          │ updated:                                                                     │
│                         │          │   spec:                                                                      │
│                         │          │     template:                                                                │
│                         │          │       spec:                                                                  │
│                         │          │         containers:                                                          │
│                         │          │           0:                                                                 │
│                         │          │             image: nginx:1.20.0-alpine                                       │
│                         │          │                                                                              │
└─────────────────────────┴──────────┴──────────────────────────────────────────────────────────────────────────────┘


┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Plan summary for provider k8s                                                                                    │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ DEPLOY RESOURCES                                                                                                 │
├────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────────┤
│ Deployment         │ myapp::nginx-deployment                                                                     │
└────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────┘
? Are you sure to deploy 1 resource, 1 type on 1 provider? › (y/N)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice this time the action is not &lt;code&gt;CREATE&lt;/code&gt; but &lt;code&gt;UPDATE&lt;/code&gt;. &lt;strong&gt;gc&lt;/strong&gt; fetched the live resources from the &lt;em&gt;kubernetes-api-server&lt;/em&gt;, compared them with the target resources defined in the code, and has found out the deployment needs to be updated.&lt;/p&gt;

&lt;p&gt;Now we can apply the change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The updated Nginx image should be up and running.&lt;/p&gt;

&lt;p&gt;Let's double-check the state of the Nginx deployment, filtering by &lt;em&gt;type&lt;/em&gt; and &lt;em&gt;name&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc list &lt;span class="nt"&gt;-t&lt;/span&gt; Deployment &lt;span class="nt"&gt;--name&lt;/span&gt; nginx-deployment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Listing resources on 1 provider: k8s
✓ k8s
  ✓ Initialising
  ✓ Listing 6/6
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 1 Deployment from k8s                                                                                             │
├─────────────────────────┬──────────────────────────────────────────────────────────────────────────────────┬──────┤
│ Name                    │ Data                                                                             │ Our  │
├─────────────────────────┼──────────────────────────────────────────────────────────────────────────────────┼──────┤
│ myapp::nginx-deployment │ metadata:                                                                        │ Yes  │
│                         │   name: nginx-deployment                                                         │      │
│                         │   namespace: myapp                                                               │      │
│                         │   uid: 7c9bf366-cbf4-47d9-a7b7-e3da900b75dc                                      │      │
│                         │   resourceVersion: 7111                                                          │      │
│                         │   generation: 2                                                                  │      │
│                         │   creationTimestamp: 2021-04-28T19:51:37Z                                        │      │
│                         │   labels:                                                                        │      │
│                         │     app: nginx-label                                                             │      │
│                         │   annotations:                                                                   │      │
│                         │     CreatedByProvider: k8s                                                       │      │
│                         │     ManagedBy: GruCloud                                                          │      │
│                         │     Name: nginx-deployment                                                       │      │
│                         │     deployment.kubernetes.io/revision: 2                                         │      │
│                         │     projectName: @grucloud/example-k8s-tuto1                                     │      │
│                         │     stage: dev                                                                   │      │
│                         │ spec:                                                                            │      │
│                         │   replicas: 1                                                                    │      │
│                         │   selector:                                                                      │      │
│                         │     matchLabels:                                                                 │      │
│                         │       app: nginx-label                                                           │      │
│                         │   template:                                                                      │      │
│                         │     metadata:                                                                    │      │
│                         │       creationTimestamp: null                                                    │      │
│                         │       labels:                                                                    │      │
│                         │         app: nginx-label                                                         │      │
│                         │     spec:                                                                        │      │
│                         │       containers:                                                                │      │
│                         │         - name: nginx                                                            │      │
│                         │           image: nginx:1.20.0-alpine                                             │      │
│                         │           ports:                                                                 │      │
│                         │             - containerPort: 80                                                  │      │
│                         │               protocol: TCP                                                      │      │
│                         │           resources:                                                             │      │
│                         │           terminationMessagePath: /dev/termination-log                           │      │
│                         │           terminationMessagePolicy: File                                         │      │
│                         │           imagePullPolicy: IfNotPresent                                          │      │
│                         │       restartPolicy: Always                                                      │      │
│                         │       terminationGracePeriodSeconds: 30                                          │      │
│                         │       dnsPolicy: ClusterFirst                                                    │      │
│                         │       securityContext:                                                           │      │
│                         │       schedulerName: default-scheduler                                           │      │
│                         │   strategy:                                                                      │      │
│                         │     type: RollingUpdate                                                          │      │
│                         │     rollingUpdate:                                                               │      │
│                         │       maxUnavailable: 25%                                                        │      │
│                         │       maxSurge: 25%                                                              │      │
│                         │   revisionHistoryLimit: 10                                                       │      │
│                         │   progressDeadlineSeconds: 600                                                   │      │
│                         │ status:                                                                          │      │
│                         │   observedGeneration: 2                                                          │      │
│                         │   replicas: 1                                                                    │      │
│                         │   updatedReplicas: 1                                                             │      │
│                         │   readyReplicas: 1                                                               │      │
│                         │   availableReplicas: 1                                                           │      │
│                         │   conditions:                                                                    │      │
│                         │     - type: Available                                                            │      │
│                         │       status: True                                                               │      │
│                         │       lastUpdateTime: 2021-04-28T19:51:39Z                                       │      │
│                         │       lastTransitionTime: 2021-04-28T19:51:39Z                                   │      │
│                         │       reason: MinimumReplicasAvailable                                           │      │
│                         │       message: Deployment has minimum availability.                              │      │
│                         │     - type: Progressing                                                          │      │
│                         │       status: True                                                               │      │
│                         │       lastUpdateTime: 2021-04-28T20:03:08Z                                       │      │
│                         │       lastTransitionTime: 2021-04-28T19:51:37Z                                   │      │
│                         │       reason: NewReplicaSetAvailable                                             │      │
│                         │       message: ReplicaSet "nginx-deployment-675bd9f4f7" has successfully progre… │      │
│                         │                                                                                  │      │
└─────────────────────────┴──────────────────────────────────────────────────────────────────────────────────┴──────┘


List Summary:
Provider: k8s
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ k8s                                                                                                              │
├────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────────┤
│ Deployment         │ myapp::nginx-deployment                                                                     │
└────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────┘
1 resource, 5 types, 1 provider
Command "gc list -t Deployment --name nginx-deployment" executed in 0s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great, as expected, the new version has been updated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Destroy
&lt;/h3&gt;

&lt;p&gt;To destroy the resources allocated in the right order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Destroy summary for provider k8s                                                                                 │
├────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────────┤
│ Namespace          │ myapp                                                                                       │
├────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤
│ Service            │ myapp::nginx-service                                                                        │
├────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤
│ Deployment         │ myapp::nginx-deployment                                                                     │
└────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────┘
✔ Are you sure to destroy 3 resources, 3 types on 1 provider? … yes
Destroying resources on 1 provider: k8s
✓ k8s
  ✓ Initialising
  ✓ Destroying
    ✓ Namespace 1/1
    ✓ Service 1/1
    ✓ Deployment 1/1
  ✓ default::onDestroyed
3 resources destroyed, 3 types on 1 provider
Running OnDestroyedGlobal resources on 1 provider: k8s
Command "gc d" executed in 1m 17s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this stage, all the Kubernetes resources should have been destroyed.&lt;br&gt;
We could try to run &lt;em&gt;gc destroy&lt;/em&gt; command again, nothing should be destroyed or deployed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Find Deletable resources on 1 provider: k8s
✓ k8s
  ✓ Initialising
  ✓ Listing 7/7

No resources to destroy
Running OnDestroyedGlobal resources on 1 provider: k8s
Command "gc d" executed in 0s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As expected, the &lt;em&gt;destroy&lt;/em&gt; command is idempotent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging
&lt;/h2&gt;

&lt;p&gt;A benefit of using a general-purpose programming such as Javascript, is debugging. Thanks &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt; for providing such an easy way to debug Javascript applications.&lt;/p&gt;

&lt;p&gt;This example contains a vs code file called &lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/k8s/tuto1/.vscode/launch.json" rel="noopener noreferrer"&gt;launch.json&lt;/a&gt;, which defines various debug targets for &lt;code&gt;gc apply&lt;/code&gt;, &lt;code&gt;gc destroy&lt;/code&gt; and so on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This tutorial described how to deploy, list, and destroy Kubernetes manifests from Javascript code.&lt;br&gt;
In this case, a namespace, a service, and a deployment.&lt;/p&gt;

&lt;p&gt;What's next? Let's see how to deploy a &lt;a href="https://github.com/grucloud/grucloud/tree/main/examples/starhackit/minikube" rel="noopener noreferrer"&gt;full stack application on minikube&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ready to try Kubernetes on EKS, the Amazon Elastic Kubernetes Service? Have a look at the project &lt;a href="https://github.com/grucloud/grucloud/tree/main/examples/starhackit/eks-lean" rel="noopener noreferrer"&gt;full stack application on EKS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Maybe you prefer using &lt;a href="https://kops.sigs.k8s.io/" rel="noopener noreferrer"&gt;kops&lt;/a&gt; to set up your cluster? The tutorial &lt;a href="https://dev.to/fredericheem/setup-kops-on-aws-with-grucloud-oia"&gt;Setup Kops on AWS with Grucloud&lt;/a&gt; explains how to automate the &lt;em&gt;kops&lt;/em&gt; setup&lt;/p&gt;

&lt;p&gt;Are you looking to install the &lt;em&gt;cert manager&lt;/em&gt;, &lt;em&gt;web ui dashboard&lt;/em&gt;, &lt;em&gt;prometheus&lt;/em&gt;, and more? Browse the &lt;a href="https://www.grucloud.com/docs/k8s/K8sModules" rel="noopener noreferrer"&gt;GruCloud K8s Modules&lt;/a&gt; and find out how to install and use these npm packages into your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/grucloud/grucloud" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com/docs/Introduction" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/grucloud_iac" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>iac</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Setup KOPS on AWS with GruCloud
</title>
      <dc:creator>Frederic</dc:creator>
      <pubDate>Mon, 26 Apr 2021 15:46:54 +0000</pubDate>
      <link>https://dev.to/fredericheem/setup-kops-on-aws-with-grucloud-oia</link>
      <guid>https://dev.to/fredericheem/setup-kops-on-aws-with-grucloud-oia</guid>
      <description>&lt;p&gt;The aim of this tutorial is to automatically create and destroy the AWS resources required by &lt;a href="https://kops.sigs.k8s.io/"&gt;kops&lt;/a&gt;, a tool to create a Kubernetes cluster.&lt;/p&gt;

&lt;p&gt;The section &lt;a href="https://kops.sigs.k8s.io/getting_started/aws/#setup-your-environment"&gt;'setup your environment'&lt;/a&gt; from the official &lt;em&gt;kops&lt;/em&gt; documentation will be automated with &lt;a href="https://grucloud.com"&gt;GruCloud&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below is the diagram generated from the target code, it illustrates the resources and their association with each other:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gZzky_7S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/examples/aws/kops/diagram-target.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gZzky_7S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/examples/aws/kops/diagram-target.svg" alt="kops-graph"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Regarding this DNS scenario, the case of a subdomain where a top-level hosted zone already exists is implemented.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  TD;DR
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Get this &lt;a href="https://github.com/grucloud/grucloud/tree/main/examples/aws/kops"&gt;example code&lt;/a&gt; and install the dependencies.&lt;/li&gt;
&lt;li&gt;Edit the configuration file and set the domain name, the subdomain name, the region, and the zone.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gc apply&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All the AWS resources required by kops should have been created. The environment file &lt;em&gt;kops.env&lt;/em&gt; containing the necessary information should have been generated too.&lt;/p&gt;

&lt;p&gt;You are now ready to &lt;a href="https://kops.sigs.k8s.io/getting_started/aws/#creating-your-first-cluster"&gt;create a cluster with kops&lt;/a&gt;,&lt;/p&gt;

&lt;p&gt;Here are a few npm scripts wrapper: &lt;code&gt;npm run kops:create&lt;/code&gt;, &lt;code&gt;npm run kops:update&lt;/code&gt; and &lt;code&gt;npm run kops:validate&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;p&gt;Here is a description of the steps that are automated:&lt;/p&gt;

&lt;h4&gt;
  
  
  IAM
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;create a kops group, attach 5 IAM policies.&lt;/li&gt;
&lt;li&gt;create a kops user, attach the user to the kops group.&lt;/li&gt;
&lt;li&gt;create access and secret key for the kops user.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Route53
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;create a hosted zone for a subdomain.&lt;/li&gt;
&lt;li&gt;create a DNS record of type &lt;em&gt;NS&lt;/em&gt; in the top-level hosted zone with the DNS servers as values from the subdomain hosted zone.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  S3
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;create an S3 bucket with encryption and versioning.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  kops.env file
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;create a file containing the environment variable for &lt;em&gt;kops&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You will be free from performing all these commands manually. The same applies to the destruction of all these resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://console.aws.amazon.com"&gt;Access to the AWS console&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS CLI configured&lt;/li&gt;
&lt;li&gt;A domain name registered on Route53.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nodejs.org"&gt;Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com/docs/cli/gc"&gt;GruCloud CLI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;

&lt;p&gt;Clone this &lt;a href="https://github.com/grucloud/grucloud"&gt;code&lt;/a&gt;, change to the &lt;a href="https://github.com/grucloud/grucloud/tree/main/examples/aws/kops"&gt;kops folder&lt;/a&gt;, install the npm dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/grucloud/grucloud
&lt;span class="nb"&gt;cd &lt;/span&gt;grucloud/examples/aws/kops
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;Edit &lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/aws/kops/config.js"&gt;config.js&lt;/a&gt; and set the &lt;em&gt;domainName&lt;/em&gt;, the &lt;em&gt;subDomainName&lt;/em&gt;, the &lt;em&gt;zone&lt;/em&gt; and the region:&lt;/p&gt;

&lt;p&gt;Double check your configuration with &lt;code&gt;gc info&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  - provider:
      name: aws
      type: aws
    stage: dev
    config:
      projectName: @grucloud/create-aws-kops
      kops:
        domainName: grucloud.org
        subDomainName: kops.example.grucloud.org
        groupName: kops
        userName: kops
      stage: dev
      zone: us-east-1a
      accountId: 4444454555555
      region: us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The domain name must be registered with Route53 &lt;strong&gt;for the current AWS user&lt;/strong&gt;.&lt;br&gt;
Let's also verify that a top level hosted zone already exists.&lt;br&gt;
You could use the &lt;em&gt;gc list&lt;/em&gt; command with the &lt;em&gt;Route53Domain&lt;/em&gt; and &lt;em&gt;HostedZone&lt;/em&gt; type filter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc list  &lt;span class="nt"&gt;-t&lt;/span&gt; Route53Domain &lt;span class="nt"&gt;-t&lt;/span&gt; HostedZone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[...Truncated]
┌─────────────────────────────────────────────────────────────────────────────────────────────┐
│ aws                                                                                         │
├────────────────────┬────────────────────────────────────────────────────────────────────────┤
│ Route53Domain      │ grucloud.org                                                           │
├────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ HostedZone         │ grucloud.org.                                                          │
└────────────────────┴────────────────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  iac.js
&lt;/h2&gt;

&lt;p&gt;For your information, the architecture is described in &lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/aws/kops/iac.js"&gt;iac.js&lt;/a&gt;.&lt;br&gt;
In this use, the cloud provider is AWS, so we'll use the &lt;a href="https://www.npmjs.com/package/@grucloud/provider-aws"&gt;GruCloud AWS Provider&lt;/a&gt; to create the resources.&lt;/p&gt;
&lt;h2&gt;
  
  
  Target Graph
&lt;/h2&gt;

&lt;p&gt;Another way to explore the &lt;em&gt;iac.js&lt;/em&gt; is to generate a diagram of the target resources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc graph
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deploying
&lt;/h2&gt;

&lt;p&gt;Ready to deploy the user, group, s3 bucket, route53 hosted zone and record ?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AWS resources should have been deployed.&lt;br&gt;
Let's find out our live resources as well as a diagram showing the dependencies between these resources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc list &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--our&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────────────────────────────────────┐
│ aws                                                                                         │
├────────────────────┬────────────────────────────────────────────────────────────────────────┤
│ IamPolicy          │ AmazonEC2FullAccess                                                    │
│                    │ AmazonRoute53FullAccess                                                │
│                    │ AmazonS3FullAccess                                                     │
│                    │ IAMFullAccess                                                          │
│                    │ AmazonVPCFullAccess                                                    │
├────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ IamGroup           │ kops                                                                   │
├────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ S3Bucket           │ kops.example.grucloud.org                                              │
├────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ IamUser            │ kops                                                                   │
├────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ HostedZone         │ kops.example.grucloud.org.                                             │
│                    │ grucloud.org.                                                          │
├────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ Route53Record      │ kops.example.grucloud.org-ns                                           │
└────────────────────┴────────────────────────────────────────────────────────────────────────┘
11 resources, 15 types, 1 provider
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lXu6g0C5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/examples/aws/kops/diagram-live-partial.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lXu6g0C5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/examples/aws/kops/diagram-live-partial.svg" alt="diagram-live.partial.svg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Envirornment variables
&lt;/h2&gt;

&lt;p&gt;At the end of the deployment, the environment file &lt;strong&gt;kops.env&lt;/strong&gt; is generated with the variables required by &lt;em&gt;kops&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# kops.env&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;XXXXXXNBM2ZQEPXXXXX
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;XXXXXiXmSB3aZTK/AxOOvSPcGby3XXXXXX
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kops.example.grucloud.org
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;KOPS_STATE_STORE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;s3://kops.example.grucloud.org
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eu-west-2
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ZONE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eu-west-2a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Source with variables with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source &lt;/span&gt;kops.env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the deploment is destroyed with &lt;em&gt;gc destroy&lt;/em&gt;, &lt;strong&gt;kops.env&lt;/strong&gt; is removed.&lt;/p&gt;

&lt;p&gt;The file &lt;a href="https://github.com/grucloud/grucloud/blob/main/examples/aws/kops/hook.js"&gt;hook.js&lt;/a&gt; is the place where this logic is implemented.&lt;/p&gt;

&lt;h2&gt;
  
  
  NPM kops scripts
&lt;/h2&gt;

&lt;p&gt;The following npm scripts manage the kops commands, the environment variables are sourced from &lt;strong&gt;kops.env&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run kops:create
npm run kops:update
npm run kops:validate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  List Resources
&lt;/h2&gt;

&lt;p&gt;Let's fetch all the live resources, we'll see that &lt;em&gt;kops&lt;/em&gt; creates many resources such as autoscaling groups, ec2 instances, subnets, vpc, internet gateway, volumes, key pair and so on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gc list &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;--default-exclude&lt;/span&gt; &lt;span class="nt"&gt;--types-exclude&lt;/span&gt; Certificate &lt;span class="nt"&gt;--types-exclude&lt;/span&gt; Route53Domain &lt;span class="nt"&gt;--types-exclude&lt;/span&gt; NetworkInterface
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DmEpJC1I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/examples/aws/kops/diagram-live-all.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DmEpJC1I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/grucloud/grucloud/main/examples/aws/kops/diagram-live-all.svg" alt="kops-diagram-live-all"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You could inspect and generate a diagram of any existing AWS infrastruture for the &lt;a href="https://github.com/grucloud/grucloud/tree/main/packages/providers/aws#resources"&gt;most used resources&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Destroy
&lt;/h2&gt;

&lt;p&gt;To destroy the resources created by GruCloud, use the &lt;em&gt;destroy&lt;/em&gt; command.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ensure the cluster is destroyed before.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run kops:destroy
gc destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, &lt;em&gt;gc&lt;/em&gt; could also destroy all the resources created by &lt;em&gt;kops&lt;/em&gt;, use the &lt;em&gt;all&lt;/em&gt; flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gc destroy --all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Further Step
&lt;/h2&gt;

&lt;p&gt;Congratulations, you know how to create and destroy a Kubernetes cluster with &lt;em&gt;kops&lt;/em&gt;.&lt;br&gt;
What about a load balancer, DNS records, SSL certificates ? Grucloud provides some ready made modules distributed with &lt;em&gt;npm&lt;/em&gt;, the node package manager.&lt;/p&gt;

&lt;p&gt;Have a look at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/@grucloud/module-aws-certificate"&gt;@grucloud/module-aws-certificate&lt;/a&gt;: Create a certificate and a Route53 record for validation.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/@grucloud/module-aws-load-balancer"&gt;@grucloud/module-aws-load-balancer&lt;/a&gt;: Manage a load balancer, target groups, listeners and rules. A leaner alternative the AWS Load Balancer Controller which runs on the cluster.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/@grucloud/module-aws-vpc"&gt;@grucloud/module-aws-vpc&lt;/a&gt;: Contains the base resources required to create a Kubernetes cluster.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the Kubernetes side, be aware of the &lt;a href="https://www.npmjs.com/package/@grucloud/provider-k8s"&gt;GruCloud Kubernetes Provider&lt;/a&gt;. In a nutshell, instead of writing YAML manifest, Javascript is used instead to define the manifests, no more templating engine, enjoy a real programming language instead.&lt;/p&gt;

&lt;p&gt;Would you like to deploy a &lt;a href="https://github.com/FredericHeem/starhackit"&gt;full stack application&lt;/a&gt; on EKS ? Choose the flavour depending on who is reponsible to create the load balancer, target groups, listener and rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Load balancer resources created inside the cluster with the AWS Load Balancer Controller: &lt;a href="https://github.com/grucloud/grucloud/tree/main/examples/starhackit/eks-lbc"&gt;eks-lbc&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A leaner solution where the load balancer resources are created by GruCLoud outside the cluster: &lt;a href="https://github.com/grucloud/grucloud/tree/main/examples/starhackit/eks-lean"&gt;eks-lean&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/grucloud/grucloud"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com/docs/Introduction"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.grucloud.com"&gt;Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/grucloud_iac"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>kops</category>
      <category>iac</category>
    </item>
  </channel>
</rss>
