<?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: Thulasiraj Komminar</title>
    <description>The latest articles on DEV Community by Thulasiraj Komminar (@thulasirajkomminar).</description>
    <link>https://dev.to/thulasirajkomminar</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%2F1158600%2F40c19bc8-8b00-49af-a049-b8ff27bd3804.jpeg</url>
      <title>DEV Community: Thulasiraj Komminar</title>
      <link>https://dev.to/thulasirajkomminar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thulasirajkomminar"/>
    <language>en</language>
    <item>
      <title>Understanding AWS Lambda Event Source Mapping</title>
      <dc:creator>Thulasiraj Komminar</dc:creator>
      <pubDate>Fri, 27 Dec 2024 20:33:48 +0000</pubDate>
      <link>https://dev.to/aws-builders/understanding-aws-lambda-event-source-mapping-l1e</link>
      <guid>https://dev.to/aws-builders/understanding-aws-lambda-event-source-mapping-l1e</guid>
      <description>&lt;p&gt;Attending AWS re:Invent is always a highlight for me, and this year’s session, SVS407-R: Understanding AWS Lambda Event Source Mapping, turned out to be a goldmine of insights. As someone who builds and maintains event-driven architectures, I walked away with a deeper understanding of the complexities and best practices around Event Source Mapping (ESM), particularly in handling event streams from services like Amazon Kinesis, DynamoDB Streams, and Amazon SQS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04wiv4m8kfn0cmzy3gpa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04wiv4m8kfn0cmzy3gpa.png" alt="Image description" width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The Fundamentals: Event Source Mapping in AWS Lambda
&lt;/h1&gt;

&lt;p&gt;To kick things off, the speaker provided an overview of how AWS Lambda integrates with event sources through ESM. Event source mapping ensures that Lambda functions are automatically triggered as new events arrive, making it a crucial component for real-time and asynchronous workloads. The session quickly moved into advanced topics, focusing on optimizing performance, ensuring fault tolerance, and managing error scenarios.&lt;/p&gt;

&lt;h1&gt;
  
  
  Partition Key Management: The Core of Event Order
&lt;/h1&gt;

&lt;p&gt;One of the key concepts covered was partition key management in systems like Amazon Kinesis and DynamoDB Streams. These partition keys play a vital role in ensuring order and scalability:&lt;/p&gt;

&lt;h2&gt;
  
  
  Sequential Processing Within Shards:
&lt;/h2&gt;

&lt;p&gt;Events with the same partition key are processed sequentially within their shard. This guarantees that related events (e.g., all transactions for a user) are handled in order. However, if retries or failures cause events to arrive out of order, consistency issues can arise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shard Behavior:
&lt;/h2&gt;

&lt;p&gt;Shards are responsible for processing sets of partition keys, and they scale horizontally to handle increased event volumes. Even as the system scales, the partition key ensures that related events are processed within the same shard, preserving order.&lt;/p&gt;

&lt;p&gt;This deep dive reinforced the importance of designing systems with careful consideration of partition key selection to balance performance and maintain order.&lt;/p&gt;

&lt;h1&gt;
  
  
  Error Handling in Distributed Systems: Preventing Bottlenecks
&lt;/h1&gt;

&lt;p&gt;Error handling emerged as a critical focus area in the session. Distributed systems, especially those processing real-time event streams, require robust strategies to handle failures without cascading effects. Key insights included:&lt;/p&gt;

&lt;h2&gt;
  
  
  Infinite Retries and Dead Letter Queues (DLQs):
&lt;/h2&gt;

&lt;p&gt;Without proper error handling, a shard encountering persistent errors could end up in an infinite retry loop, stalling other events in the shard. Routing unresolvable errors to DLQs, such as SQS or S3, ensures failed events are isolated and can be analyzed or resolved manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Failure Isolation:
&lt;/h2&gt;

&lt;p&gt;Kinesis-specific event source mappings allow retrying failed records individually or in smaller batches. This prevents an entire shard from stalling due to one problematic record.&lt;/p&gt;

&lt;p&gt;These practices are invaluable for maintaining the reliability of event-driven systems while ensuring that errors are handled gracefully.&lt;/p&gt;

&lt;h1&gt;
  
  
  Performance Optimization: Parallelization, Batch Processing, and Scaling
&lt;/h1&gt;

&lt;p&gt;The session also addressed parallelization and batch processing, two critical levers for optimizing performance in Lambda-based architectures:&lt;/p&gt;

&lt;h2&gt;
  
  
  Parallelization Factor:
&lt;/h2&gt;

&lt;p&gt;The parallelization factor controls how many workers process events from a single shard concurrently. While a higher factor improves throughput, it can introduce challenges in maintaining event order across partition keys. The speaker emphasized tuning this setting to match workload complexity and downstream capacity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Batch Processing and Error Mitigation:
&lt;/h2&gt;

&lt;p&gt;Features like bisect batch on error allow Lambda to split failed batches into smaller subsets, isolating problematic records for retries. This reduces redundant retries and improves system efficiency.Additionally, batch item failure reporting lets Lambda identify specific records in a failed batch, ensuring only those records are retried or sent to a DLQ.&lt;/p&gt;

&lt;h1&gt;
  
  
  Kinesis-Specific Features: A Competitive Edge
&lt;/h1&gt;

&lt;p&gt;The session highlighted several features unique to Amazon Kinesis that make it particularly powerful for event-driven architectures:&lt;/p&gt;

&lt;h2&gt;
  
  
  Error Recovery:
&lt;/h2&gt;

&lt;p&gt;With tools like checkpointing and offset management, Kinesis ensures graceful recovery from errors without reprocessing already-successful events.&lt;/p&gt;

&lt;h2&gt;
  
  
  Batch Item Failure:
&lt;/h2&gt;

&lt;p&gt;This feature complements bisect batch by isolating failed records within a batch, making retries even more precise.&lt;/p&gt;

&lt;p&gt;The speaker contrasted these capabilities with Kafka, noting that while Kafka offers flexibility, it lacks the granular error-handling features natively provided by Kinesis. Developers using Kafka often have to build custom solutions for similar functionality, increasing complexity.&lt;/p&gt;

&lt;h1&gt;
  
  
  Scaling Challenges: Balancing Upstream and Downstream Loads
&lt;/h1&gt;

&lt;p&gt;Scaling event-driven architectures can be tricky, especially when traffic spikes or downstream systems face capacity limits. Key points included:&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Traffic Spikes:
&lt;/h2&gt;

&lt;p&gt;Lambda and Kinesis scale efficiently to handle spikes, but parameters like shard count, parallelization factor, and batch size need fine-tuning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Downstream System Limits:
&lt;/h2&gt;

&lt;p&gt;Scaling upstream services is relatively easy, but downstream systems like databases or APIs often have rate limits. Strategies like throttling, backpressure mechanisms, and pre-filtering events can prevent overwhelming these systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Record Filters:
&lt;/h2&gt;

&lt;p&gt;Pre-filtering events at the Kinesis or Lambda level ensures only relevant events are processed, reducing unnecessary load on downstream components.&lt;/p&gt;

&lt;h1&gt;
  
  
  Best Practices: Building Robust Event-Driven Systems
&lt;/h1&gt;

&lt;p&gt;To wrap up the session, the speaker shared actionable best practices for building and maintaining event-driven architectures:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set Up DLQs and Monitoring:&lt;/strong&gt;&lt;br&gt;
Always configure DLQs for unresolved errors and monitor them for analysis. Use alarms to track error rates and address issues proactively.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tune Parallelization Factor:&lt;/strong&gt;&lt;br&gt;
Match the parallelization factor to your workload complexity and downstream capacity to optimize throughput.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monitor Metrics:&lt;/strong&gt;&lt;br&gt;
Regularly monitor metrics for Lambda, Kinesis, and downstream systems to identify bottlenecks and failure patterns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Batch Size Optimization:&lt;/strong&gt;&lt;br&gt;
Adjust batch sizes to balance latency, throughput, and error isolation based on workload characteristics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Graceful Error Handling:&lt;/strong&gt;&lt;br&gt;
Leverage features like bisect batch on error, batch item failure, and retry strategies to handle errors without disrupting the entire pipeline.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;The SVS407-R session at AWS re:Invent was a deep dive into the intricacies of AWS Lambda event source mapping. From partition key management and error handling to performance optimization and scaling strategies, the session provided a wealth of practical knowledge for building robust, scalable event-driven systems.&lt;/p&gt;

&lt;p&gt;One of the biggest takeaways for me was the importance of balancing throughput, order guarantees, and error isolation. Whether you’re processing billions of events with Kinesis or handling asynchronous workflows with SQS, these strategies can make all the difference in ensuring system reliability and efficiency.&lt;/p&gt;

&lt;p&gt;AWS re:Invent continues to deliver world-class learning experiences, and this session was no exception. I’m excited to apply these insights to my projects and see the impact firsthand. If you’re building event-driven applications, I highly recommend exploring these features and best practices.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="//serverlessland.com"&gt;serverlessland.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://serverlessland.com/learning-serverless" rel="noopener noreferrer"&gt;https://serverlessland.com/learning-serverless&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/aws-powertools" rel="noopener noreferrer"&gt;https://github.com/aws-powertools&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>kinesis</category>
      <category>lambda</category>
    </item>
    <item>
      <title>Terraform Stacks</title>
      <dc:creator>Thulasiraj Komminar</dc:creator>
      <pubDate>Wed, 30 Oct 2024 20:01:42 +0000</pubDate>
      <link>https://dev.to/thulasirajkomminar/terraform-stacks-610</link>
      <guid>https://dev.to/thulasirajkomminar/terraform-stacks-610</guid>
      <description>&lt;p&gt;Ever since the private preview of Terraform Stacks, I’ve been eager to dive in and explore this new approach to provisioning infrastructure. After a year in private preview, the public beta was finally announced at HashiConf 2024, and I’m excited to share my experience!&lt;/p&gt;

&lt;p&gt;In this blog, I’ll walk you through the essentials of Terraform Stacks configurations and demonstrate how to deploy a REST API as an S3 proxy using API Gateway.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiw9ulf94g9ytl1tg1wze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiw9ulf94g9ytl1tg1wze.png" width="800" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Stack?
&lt;/h3&gt;

&lt;p&gt;Terraform excels at planning and applying changes to individual resources, but it has historically lacked a built-in solution for consistently deploying identical infrastructure across multiple environments or cloud regions. To work around this, many of us developed our own methods. Personally, I’ve used workspaces for environment-specific configurations and duplicated code with different providers for multi-region setups. However, this approach sacrifices the DRY (Don’t Repeat Yourself) principle and requires stitching together dependencies manually, complicating state management and orchestration.&lt;/p&gt;

&lt;p&gt;Terraform Stacks are designed to streamline the coordination, deployment, and lifecycle management of complex, interdependent configurations. With Stacks, we can easily replicate infrastructure across environments and regions, set orchestration rules, and automate the propagation of changes, drastically reducing time and operational overhead.&lt;/p&gt;

&lt;p&gt;In essence, Stacks address the “bigger picture” of infrastructure provisioning, offering a scalable solution to manage consistent, repeatable deployments across environments and regions.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Continue to read this blog *&lt;/em&gt; &lt;a href="https://www.thulasirajkomminar.com/posts/terraform-stacks" rel="noopener noreferrer"&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>multiaccount</category>
      <category>multiregion</category>
      <category>terraform</category>
      <category>terraformstacks</category>
    </item>
    <item>
      <title>Data Governance on AWS using DataZone</title>
      <dc:creator>Thulasiraj Komminar</dc:creator>
      <pubDate>Thu, 08 Aug 2024 23:08:25 +0000</pubDate>
      <link>https://dev.to/aws-builders/data-governance-on-aws-using-datazone-4li2</link>
      <guid>https://dev.to/aws-builders/data-governance-on-aws-using-datazone-4li2</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In this blog, we will provide a brief introduction to data governance and show how to implement it on AWS using DataZone. We will walk through a practical example involving a multi-account setup to manage and share data stored in S3 and Redshift, highlighting key steps and best practices along the way.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Data Governance?
&lt;/h3&gt;

&lt;p&gt;Data governance is everything you do to ensure data is secure, private, accurate, available, and usable that helps organizations accelerate data-driven decisions. Key steps in implementing data governance typically include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data mapping and classification.&lt;/strong&gt;
Data mapping involves documenting data assets and understanding how data flows through an organization’s systems. This process enables the identification of different data sets, which can then be classified based on various factors, such as whether they contain personal information or other sensitive data. These classifications directly influence the application of data governance policies to each data set, ensuring appropriate levels of security and compliance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Business glossary.&lt;/strong&gt;
A business glossary provides standardized definitions for business terms and concepts used within an organization. For instance, it might define what constitutes an &lt;em&gt;active customer&lt;/em&gt;. By establishing a common vocabulary for business data, a business glossary supports consistent understanding and interpretation, which is crucial for effective governance across the organization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data catalog.&lt;/strong&gt;
A data catalog is a comprehensive, indexed inventory of an organization’s data assets, created by collecting metadata from various systems. It typically includes details on data lineage, search functionalities, and collaboration tools. Data catalogs often integrate information about data governance policies and offer automated mechanisms for policy enforcement, ensuring that data is used in accordance with established governance standards.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What is AWS DataZone?
&lt;/h3&gt;

&lt;p&gt;DataZone is a data management service that makes it faster and easier for customers to catalog, discover, share, and govern data stored across AWS accounts. With DataZone, administrators and data stewards who oversee an organization’s data assets can manage and govern access to data using fine-grained controls. These controls are designed to ensure access with the right level of privileges and context. DataZone makes it easier for engineers, data scientists, product managers, analysts, and business users to access data throughout an organization so that they can discover, use, and collaborate to derive data-driven insights.&lt;/p&gt;

&lt;h4&gt;
  
  
  Key concepts and Capabilities:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Data Portal&lt;/strong&gt;
This is a web application where different users can go to catalog, discover, govern, share, and analyze data in a self-service fashion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Business Data Catalog&lt;/strong&gt;
In your catalog, you can define the taxonomy or the business glossary. You can use this component to catalog data across your organization with business context and thus enable everyone in your organization to ﬁnd and understand data quickly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Projects &amp;amp; Environments&lt;/strong&gt;
You can use projects to simplify access to the AWS analytics by creating business use case–based groupings of people, data assets, and analytics tools. DataZone projects provide a space where project members can collaborate, exchange data, and share data assets. Within projects, you can create environments that provide the necessary infrastructure to project members such as analytics tools and storage so that project members can easily produce new data or consume data they have access to.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Governance and Access Control&lt;/strong&gt;
You can use built-in workflows that allow users across the organization to request access to data in the catalog and owners of the data to review and approve those subscription requests. Once a subscription request is approved, DataZone can automatically grant access by managing permission at underlying data stores such as Lake Formation and Redshift.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Setting up DataZone
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Set up Redshift Serverless clusters in both the Producer and Consumer accounts. This is essential for enabling database sharing across accounts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that we’ve explored the fundamentals of data governance and the key concepts of DataZone, let’s move forward with the setup process.&lt;/p&gt;

&lt;h4&gt;
  
  
  Architecture
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u3Sw9YQT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A4hrC1ymOejuOAWcLAL9p0w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u3Sw9YQT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A4hrC1ymOejuOAWcLAL9p0w.png" width="800" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  DataZone Account
&lt;/h4&gt;

&lt;p&gt;In an organization, a central Data Team is typically responsible for setting up and managing the data marketplace using DataZone. Their key responsibilities include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Building Security Controls&lt;/em&gt;&lt;/strong&gt; : Implementing robust security measures to protect data assets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Developing and Operating the Platform&lt;/em&gt;&lt;/strong&gt; : Ensuring the data marketplace is built and maintained for seamless operation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Simplifying Onboarding&lt;/em&gt;&lt;/strong&gt; : Facilitating the onboarding process by creating training materials and actively engaging with the community.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To begin setting up a Data Marketplace, the first step is to create a domain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create DataZone Domain:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Login to the &lt;strong&gt;AWS Console&lt;/strong&gt; as an administrator user, then navigate to Amazon DataZone.&lt;/li&gt;
&lt;li&gt;Click on the &lt;strong&gt;Create domain&lt;/strong&gt;  button.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NlRXm8KR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AHBbeV9TAYix9Hh6j14g5SA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NlRXm8KR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AHBbeV9TAYix9Hh6j14g5SA.png" width="800" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On the &lt;strong&gt;Create domain&lt;/strong&gt; page, provide values for the following fields:
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain Name:&lt;/strong&gt; The name of the domain.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; This is an optional field where you can provide a description for this root domain.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service access:&lt;/strong&gt; DataZone will create a new service role for you if there is no suitable role exists in your AWS account. This role includes necessary permissions that authorize DataZone to make API calls on behalf of users within the domain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qBCYlHmv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AtfzPSr1k7IrwSr_-fRwozg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qBCYlHmv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AtfzPSr1k7IrwSr_-fRwozg.png" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quick set up:&lt;/strong&gt; Select this option as it automatically creates required service roles and S3 bucket required for DataZone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LpTAqJax--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AlDz-mi6DfBQCjIJ4YsuLMA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LpTAqJax--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AlDz-mi6DfBQCjIJ4YsuLMA.png" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on &lt;strong&gt;Create domain&lt;/strong&gt;. Once the domain is created click &lt;strong&gt;Open data portal&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Associate Producer and Consumer accounts:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Associating your AWS accounts with DataZone domains enables you to publish data from these AWS accounts into the DataZone catalog and create DataZone projects to work with your data across multiple AWS accounts. Now the Data Portal is ready lets associate the producer and the consumer accounts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the domains, click on the &lt;strong&gt;Account associations&lt;/strong&gt; and click &lt;strong&gt;Request association&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enter the &lt;em&gt;Producer account&lt;/em&gt; id and click &lt;strong&gt;Request association&lt;/strong&gt;. Repeat this step to associate the &lt;em&gt;Consumer account&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aLrPafrV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AUg13rHpp2kIF8Qv0CC_yaQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aLrPafrV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AUg13rHpp2kIF8Qv0CC_yaQ.png" width="800" height="651"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create Projects:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Projects enable a group of users to collaborate on various business use cases that involve publishing, discovering, subscribing to, and consuming data assets in the Amazon DataZone catalog. We will create projects for producer and consumer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Log in to the Data Portal and navigate to the &lt;strong&gt;Create Project&lt;/strong&gt; option. Enter a name for your project and click &lt;strong&gt;Create&lt;/strong&gt;. Repeat this process to create the &lt;strong&gt;Consumer&lt;/strong&gt; project as well.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wtp0wEMM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ACsHpXS3drVtUMb-jOQw0qA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wtp0wEMM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ACsHpXS3drVtUMb-jOQw0qA.png" width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the projects set up and the Producer and Consumer accounts linked, the next step is to enable blueprints in both the &lt;em&gt;Producer and Consumer accounts&lt;/em&gt;. Once this is done, we’ll return to the DataZone account to create environments, establish a business catalog, and then publish and subscribe to data assets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create Environments:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In DataZone projects, environments are defined as collections of configured resources — such as S3 buckets, Glue databases, or Athena workgroups — each associated with a specific set of IAM principals (user roles) who are granted owner or contributor permissions to manage those resources.&lt;/p&gt;

&lt;p&gt;In our setup, we will create two environments: one for Athena (linked with S3) and another for Redshift.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Athena Environment:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Log in to the Data Portal, select the Producer project, and then navigate to the &lt;strong&gt;Environments&lt;/strong&gt; tab. Click on &lt;strong&gt;Create Environment&lt;/strong&gt; to proceed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YdA4eNzH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AwrW7BOrlOGV3jXvB6ycroQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YdA4eNzH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AwrW7BOrlOGV3jXvB6ycroQ.png" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enter the name and choose &lt;strong&gt;DataLakeProfile&lt;/strong&gt; as environment profile and click &lt;strong&gt;Create Environment.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enter a name for the environment, select &lt;strong&gt;DataLakeProfile&lt;/strong&gt; as the environment profile, and click &lt;strong&gt;Create Environment&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--37ZmBp7u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ABzKcXB44oYJKiz04zATqoQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--37ZmBp7u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ABzKcXB44oYJKiz04zATqoQ.png" width="800" height="894"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Redshift Environment:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to the &lt;strong&gt;Environments&lt;/strong&gt; tab and click &lt;strong&gt;Create Environment Profile&lt;/strong&gt;. Enter a name for the profile and select &lt;strong&gt;Default Data Warehouse&lt;/strong&gt; as the blueprint.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yDiNOswD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Ayy5g-c-e0bjeDSGe-hZUYw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yDiNOswD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Ayy5g-c-e0bjeDSGe-hZUYw.png" width="800" height="634"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Under the &lt;strong&gt;Parameter set&lt;/strong&gt; section, select the parameter set you created earlier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z7G1dlW1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Avn29HxizX1BqZz0lkg6OgQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z7G1dlW1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Avn29HxizX1BqZz0lkg6OgQ.png" width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;Create Environment Profile&lt;/strong&gt; to complete the setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FWXoJxin--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AimGK7j1Q9rU6OBnYz4QzzQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FWXoJxin--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AimGK7j1Q9rU6OBnYz4QzzQ.png" width="800" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Producer and Consumer Account
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Enable Blueprints:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A blueprint with which the environment is created defines what AWS tools and services (eg, Glue or Redshift) members of the project to which the environment belongs can use as they work with assets in the DataZone catalog.&lt;/p&gt;

&lt;p&gt;Go to DataZone service click View Associated Domain and under the Blueprints tab enable &lt;strong&gt;Default Data Lake&lt;/strong&gt; and &lt;strong&gt;Default Data Warehouse&lt;/strong&gt; blueprints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create Parameter Set for Redshift:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Parameter set is a group of keys and values, required for DataZone to establish a connection to your Redshift cluster and is used to create data warehouse environments. These parameters include the name of your Redshift cluster, database, and the secrets manager that holds credentials to the cluster.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on the Default &lt;strong&gt;Data Warehouse blueprints&lt;/strong&gt; and under the &lt;strong&gt;Parameter sets&lt;/strong&gt; click &lt;strong&gt;Create parameter set&lt;/strong&gt;. Enter the name, description and choose the region.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Yq3LVYSU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ApPP8j8h3fnb_BZJV3M7oeA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Yq3LVYSU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ApPP8j8h3fnb_BZJV3M7oeA.png" width="800" height="659"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select either Amazon Redshift cluster or Amazon Redshift Serverless.&lt;/li&gt;
&lt;li&gt;Select the secrets manager ARN that holds the credentials to the selected Redshift cluster or the Redshift Serverless workgroup. The AWS secret must be tagged with the AmazonDataZoneDomain : [&lt;em&gt;Domain_ID&lt;/em&gt;] tag in order to be eligible for use within a parameter set.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create parameter set&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Make sure the Redshift Manage Access Role has permissions to read the secret.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2V7zpaO5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A1IbfHzuYmJXZE4QZGW2-EA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2V7zpaO5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A1IbfHzuYmJXZE4QZGW2-EA.png" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repeat the above steps in the Consumer account to mirror the setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Publishing &amp;amp; Cataloging data product
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For this tutorial create two datasets in the &lt;em&gt;Producer account&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Claims:&lt;/em&gt;&lt;/strong&gt; Create a dataset in S3 that contains information on insurance claims filed. Additionally, use the Glue Data Catalog to catalog this data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Customer:&lt;/em&gt;&lt;/strong&gt; Create a dataset in Redshift that includes personal information and relevant details about customers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With the projects and environments now created, we can proceed to import existing data, catalog it, and ultimately publish it and then will make the data easy to understand with business glossary and business name generation.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Publish Claims data&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Log in to the Data Portal, navigate to the Data Sources tab, and click on &lt;strong&gt;Create Data Source&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Enter a name for the data source, select &lt;strong&gt;AWS Glue&lt;/strong&gt; as the type (since the claims data is stored in S3), and choose the environment you just created.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RkyJBh9U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AwkbhKqAIrN4IJBNNRnM0Dg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RkyJBh9U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AwkbhKqAIrN4IJBNNRnM0Dg.png" width="800" height="589"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enter the name of the Glue database, then proceed through the subsequent tabs with the default settings. Click &lt;strong&gt;Create&lt;/strong&gt; to finalize the setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SO2Y2KV5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A1y9H_ROYeS9znLauutTbsw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SO2Y2KV5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A1y9H_ROYeS9znLauutTbsw.png" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Once the Data Source is created, initiate it to allow DataZone to import the Glue catalog into the Data Portal. After the process completes, you will see the imported asset in the portal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I3RjmhIl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ArpIUnlsF-TGenJFmJ3IMFw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I3RjmhIl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ArpIUnlsF-TGenJFmJ3IMFw.png" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on the asset to verify its details. The tables created have technical column names. DataZone provides a feature called &lt;strong&gt;Business Name Generation&lt;/strong&gt; , which converts technical names into more user-friendly business data names. Review these generated names, and if they meet your expectations, click &lt;strong&gt;Accept All&lt;/strong&gt; to apply the business data names automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Business Glossary:&lt;/em&gt;&lt;/strong&gt; In DataZone, a business glossary is a curated collection of business terms designed to enhance the clarity and understanding of data assets. These glossaries are created within the catalog’s root domain and can be linked to metadata forms across various domains. A business glossary can either be a flat list of terms or a hierarchical structure, where any term can have an associated sublist of related terms. This feature ensures that data is easier to interpret and aligns with business concepts.&lt;/li&gt;
&lt;li&gt;If needed, you can create and attach Business Glossary terms to the data asset. Once everything is in place, click &lt;strong&gt;Publish Asset&lt;/strong&gt; to make the data asset available for consumption.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Wj4X5Tqq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A2lhdYA3SnpM7shdBMZD58g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Wj4X5Tqq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A2lhdYA3SnpM7shdBMZD58g.png" width="800" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Publish Customer data&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to the Data Sources tab, create a new data source and choose &lt;strong&gt;Amazon Redshift&lt;/strong&gt; as the type.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3cu6Lbvr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A2EFHALRHlw_mCnIqQH62Vw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3cu6Lbvr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A2EFHALRHlw_mCnIqQH62Vw.png" width="800" height="595"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;Next&lt;/strong&gt; , enter the appropriate schema name, and leave the remaining settings as default. Click &lt;strong&gt;Create&lt;/strong&gt; and then run the data source. Once the run is complete, you should see the imported asset. Click on the asset and then select &lt;strong&gt;Publish&lt;/strong&gt; to finalize the process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0OUzLws---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Aau6HpYpUvSPdZwloBuOjeQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0OUzLws---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Aau6HpYpUvSPdZwloBuOjeQ.png" width="800" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Having published both datasets, the next step is to subscribe from the &lt;em&gt;Consumer account&lt;/em&gt;. Once subscribed, you can analyze the data using Athena and Redshift.&lt;/p&gt;

&lt;h3&gt;
  
  
  Discovering and subscribing data product
&lt;/h3&gt;

&lt;p&gt;Data Consumer searches for data and discovers the data needed for the business use case. They also request access to the data through data subscription. Once the Data Product Owner approves the subscription, the data asset is available for use by the Data Analyst.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Claims data&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Create subscription:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the search bar to locate the claims data and click &lt;strong&gt;Subscribe&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AUsQDZa5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AbZHw9S82LlOyHrkK_Gxn2A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AUsQDZa5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AbZHw9S82LlOyHrkK_Gxn2A.png" width="800" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BlOfdEuj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ARIXBf1GXTJk0R8dZHHtAJA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BlOfdEuj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ARIXBf1GXTJk0R8dZHHtAJA.png" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to the &lt;em&gt;Producer project&lt;/em&gt;, where a notification for the subscription request should appear. Click &lt;strong&gt;View Request&lt;/strong&gt; to review the details and approve it. You can choose to grant full access to the data or apply column/row filters as needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L890i6VF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AtLpMuFOPa0KHbHZpp9EAlQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L890i6VF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AtLpMuFOPa0KHbHZpp9EAlQ.png" width="800" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8viILELd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ANr_y7SuEGkzm6Y_1B5vERA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8viILELd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ANr_y7SuEGkzm6Y_1B5vERA.png" width="800" height="763"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analyze and Visualize data in Athena:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Return to the Consumer project, where you should now see the subscribed asset listed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6Ca0wcDX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ATyzFQWxkFVZg12mbrHrtMQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6Ca0wcDX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ATyzFQWxkFVZg12mbrHrtMQ.png" width="800" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on the subscribed asset, then go to the &lt;strong&gt;My Subscription&lt;/strong&gt; tab and select &lt;strong&gt;Query Data&lt;/strong&gt; to view the data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wR4sZsNZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AErd758YH0nUoRmKaSEfslA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wR4sZsNZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AErd758YH0nUoRmKaSEfslA.png" width="800" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zNAC1Rgf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AQkhiy9C57Zv-JjdlUIhFYw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zNAC1Rgf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AQkhiy9C57Zv-JjdlUIhFYw.png" width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Customer data&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Create subscription:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repeat the process to search for and subscribe to the customer data. Switch back to the Producer project to approve the request. Once approved, DataZone will add the asset to the existing environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5xMFcsHi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A-vc5J-RdUCRlkqMcECcNlg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5xMFcsHi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A-vc5J-RdUCRlkqMcECcNlg.png" width="800" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analyze and Visualize data in Redshift:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;Query Data&lt;/strong&gt; to run queries on the Customer data in Redshift.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4TGCQOBu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AZoLVG5SQpcZtvFcInzSgoQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4TGCQOBu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AZoLVG5SQpcZtvFcInzSgoQ.png" width="800" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For authentication, select &lt;strong&gt;Federated User&lt;/strong&gt; and use dev for the database. You should see a &lt;strong&gt;datazone_&lt;/strong&gt; schema with a view created under that schema.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5HTq9mLe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AoKu5Zrs4hKnQiJxm9RmmFg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5HTq9mLe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AoKu5Zrs4hKnQiJxm9RmmFg.png" width="800" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This blog covered setting up data governance with AWS DataZone, including creating datasets, configuring environments, and managing data access. With these steps, you can now efficiently manage and analyze data across your organization, enhancing data-driven decision-making.&lt;/p&gt;




</description>
      <category>awsdatazone</category>
      <category>glue</category>
      <category>redshift</category>
      <category>datagovernance</category>
    </item>
    <item>
      <title>How to Migrate Amazon Redshift to a Different Account and Region: Step-by-Step Guide</title>
      <dc:creator>Thulasiraj Komminar</dc:creator>
      <pubDate>Thu, 04 Jul 2024 16:01:33 +0000</pubDate>
      <link>https://dev.to/aws-builders/how-to-migrate-amazon-redshift-to-a-different-account-and-region-step-by-step-guide-2c38</link>
      <guid>https://dev.to/aws-builders/how-to-migrate-amazon-redshift-to-a-different-account-and-region-step-by-step-guide-2c38</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Moving Amazon Redshift to a new account and region might seem difficult, but it doesn’t have to be. You might need to follow regulations or reorganize your teams. In this guide, we will show you step by step how to move your Redshift data to a different account and region. After reading this guide, you will know how to do Redshift migrations easily, with minimal downtime and secure data. Let’s start and make your Redshift move simple!&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A2bxIHadaUqNZIEVYATfnQg.png" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A2bxIHadaUqNZIEVYATfnQg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;For the migration process, choose a maintenance window with minimal write activity, ensuring alignment with the organization’s RTO and RPO requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Configure cross-region snapshot
&lt;/h3&gt;

&lt;p&gt;To move the cluster to a different region in a different account, you first need to configure the cross-region snapshot for the cluster in the source account where the cluster resides.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to your cluster and click  &lt;strong&gt;Actions&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Configure cross-region snapshot&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;In the &lt;strong&gt;Destination AWS Region&lt;/strong&gt; drop-down menu, choose the region where you want to move the cluster in the target account.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Save&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&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%2Fcdn-images-1.medium.com%2Fmax%2F603%2F1%2AWFJYsV3CdYcLcDuBmHk61g.png" 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%2Fcdn-images-1.medium.com%2Fmax%2F603%2F1%2AWFJYsV3CdYcLcDuBmHk61g.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create a manual snapshot
&lt;/h3&gt;

&lt;p&gt;To share a cluster snapshot with another AWS account, you need a manual snapshot.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to your cluster and click  &lt;strong&gt;Actions&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;Create Snapshot&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Give the snapshot a name and click &lt;strong&gt;Create Snapshot&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Since we configured the cross-region snapshot in the previous step, creating a snapshot now will also copy it to the destination region.&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%2Fcdn-images-1.medium.com%2Fmax%2F602%2F1%2APTw99ispjPzsGaDk-T4OiQ.png" 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%2Fcdn-images-1.medium.com%2Fmax%2F602%2F1%2APTw99ispjPzsGaDk-T4OiQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Grant Access to KMS Key in the Target Account
&lt;/h3&gt;

&lt;p&gt;When you share an encrypted snapshot, you also need to share the KMS key that was used to encrypt it. To do this, add the following policy to the KMS key. In this policy example, replace &lt;code&gt;123456789123&lt;/code&gt; with the identifier of the TargetAccount.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"key-policy-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow use of the key in TargetAccount"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"AWS"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:iam::123456789123:root"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"kms:Decrypt"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Share snapshot
&lt;/h3&gt;

&lt;p&gt;Navigate to Snapshots, find the manual snapshot you created, and click on it. Under Snapshot access, click on edit. Enter the TargetAccount ID and click Add account. Once you’re done, click Save. Now, the snapshot will be accessible in the TargetAccount and the destination region..&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%2Fcdn-images-1.medium.com%2Fmax%2F825%2F1%2AKF38Ohf7KLC0RzKfOoOKzw.png" 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%2Fcdn-images-1.medium.com%2Fmax%2F825%2F1%2AKF38Ohf7KLC0RzKfOoOKzw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Restoring a Cluster from Snapshot in the Target Account
&lt;/h3&gt;

&lt;p&gt;Navigate to the TargetAccount and the destination region in Redshift. Under snapshots, you will find the shared snapshot. Click on Restore snapshot and configure options like Nodes, Networking, and more as needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this guide, we’ve covered the essential steps to migrate Amazon Redshift to a new account and region smoothly. By following these steps carefully, you can ensure minimal downtime and maintain data integrity throughout the migration process. I hope this guide has provided clarity and confidence for your Redshift migration journey!&lt;/p&gt;

&lt;h3&gt;
  
  
  References:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/redshift/latest/mgmt/managing-snapshots-console.html#snapshot-create" rel="noopener noreferrer"&gt;Managing snapshots using the console&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/redshift/latest/mgmt/managing-snapshots-console.html#snapshot-share" rel="noopener noreferrer"&gt;Managing snapshots using the console&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/redshift/latest/mgmt/managing-snapshots-console.html#snapshot-restore" rel="noopener noreferrer"&gt;Managing snapshots using the console&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>snapshot</category>
      <category>migration</category>
      <category>redshift</category>
      <category>aws</category>
    </item>
    <item>
      <title>Streamline SSO Access to AWS Redshift Query Editor with Okta and Terraform</title>
      <dc:creator>Thulasiraj Komminar</dc:creator>
      <pubDate>Sat, 18 May 2024 08:41:26 +0000</pubDate>
      <link>https://dev.to/aws-builders/streamline-sso-access-to-aws-redshift-query-editor-with-okta-and-terraform-5fj7</link>
      <guid>https://dev.to/aws-builders/streamline-sso-access-to-aws-redshift-query-editor-with-okta-and-terraform-5fj7</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/redshift/query-editor-v2/"&gt;AWS Redshift Query Editor v2&lt;/a&gt; is a web-based tool that allows analysts to securely explore, share, and collaborate on data using SQL within a common notebook interface. It simplifies querying data with SQL and visualizing results with charts and graphs in just a few clicks.&lt;/p&gt;

&lt;p&gt;Integrating Redshift Query Editor v2 with your identity provider (IdP) automatically redirects users to the Query Editor v2 console instead of the Amazon Redshift console. This setup enables seamless access to Amazon Redshift clusters via federated credentials, eliminating the need to manage individual database users and passwords.&lt;/p&gt;

&lt;p&gt;In this blog post, we’ll focus on using &lt;a href="https://www.okta.com/"&gt;Okta&lt;/a&gt; as the IdP and guide you through configuring your Okta application and AWS IAM permissions. We’ll also demonstrate how to restrict user access to only the Query Editor v2, preventing them from performing administrative functions on the AWS Management Console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fdHhfyZy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AfBXvXf9pTZUjNabD.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fdHhfyZy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AfBXvXf9pTZUjNabD.png" alt="https://aws.amazon.com/redshift/" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Before you begin, ensure you have the following prerequisites in place:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;An Okta Account&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;: You need an active Okta account to serve as your identity provider.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;A Redshift Cluster&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;: Ensure you have an existing Amazon Redshift cluster set up.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Configured Query Editor v2&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;: Make sure Redshift Query Editor v2 is configured. For more details, refer to&lt;/em&gt; &lt;a href="https://docs.aws.amazon.com/redshift/latest/mgmt/query-editor-v2-getting-started.html"&gt;&lt;em&gt;Configuring your AWS account&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Create IAM Roles and Permissions
&lt;/h3&gt;

&lt;p&gt;To enable Okta to access Amazon Redshift Query Editor v2, you need to create two IAM roles. The first role will be used by Okta to access the Redshift Query Editor, and the second role will establish a trust relationship between the IdP (Okta) and AWS. We’ll start by creating the role that Okta uses to access Amazon Redshift Query Editor v2. After setting up the Okta application, we’ll create the trust relationship role using the metadata from the Okta app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_caller_identity"&lt;/span&gt; &lt;span class="s2"&gt;"current"&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_region"&lt;/span&gt; &lt;span class="s2"&gt;"current"&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_policy_document"&lt;/span&gt; &lt;span class="s2"&gt;"assume_policy"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;statement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;effect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
    &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"sts:AssumeRoleWithSAML"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"sts:TagSession"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="nx"&gt;principals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Federated"&lt;/span&gt;
      &lt;span class="nx"&gt;identifiers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:iam::${data.aws_caller_identity.current.account_id}:saml-provider/OktaRedshiftFederation"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"StringEquals"&lt;/span&gt;
      &lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SAML:aud"&lt;/span&gt;
      &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"https://signin.aws.amazon.com/saml"&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="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_policy_document"&lt;/span&gt; &lt;span class="s2"&gt;"default"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;statement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"redshift:GetClusterCredentials"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"redshift:CreateClusterUser"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"redshift:JoinGroup"&lt;/span&gt;&lt;span class="p"&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="p"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"arn:aws:redshift:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:cluster:${local.redshift_cluster_id}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"arn:aws:redshift:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:dbuser:${local.redshift_cluster_id}/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"arn:aws:redshift:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:dbgroup:${local.redshift_cluster_id}/admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"arn:aws:redshift:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:dbgroup:${local.redshift_cluster_id}/datascientist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"arn:aws:redshift:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:dbname:${local.redshift_cluster_id}/*"&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="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_role"&lt;/span&gt; &lt;span class="s2"&gt;"default"&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;"RedshiftQueryEditorFederation"&lt;/span&gt;
  &lt;span class="nx"&gt;assume_role_policy&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="nx"&gt;aws_iam_policy_document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assume_policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev"&lt;/span&gt;
    &lt;span class="nx"&gt;stack&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"redshift"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_role_policy"&lt;/span&gt; &lt;span class="s2"&gt;"default"&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;"RedshiftQueryEditorFederation"&lt;/span&gt;
  &lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_iam_role&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;policy&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="nx"&gt;aws_iam_policy_document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_role_policy_attachment"&lt;/span&gt; &lt;span class="s2"&gt;"default"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_iam_role&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;policy_arn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:iam::aws:policy/AmazonRedshiftQueryEditorV2ReadSharing"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Up Okta Application
&lt;/h3&gt;

&lt;p&gt;With the IAM role for Okta access created, configure the Okta SAML application and assign it to the necessary Okta groups.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"okta_group"&lt;/span&gt; &lt;span class="s2"&gt;"admin"&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;"admin"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"okta_group"&lt;/span&gt; &lt;span class="s2"&gt;"datascientist"&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;"datascientist"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"okta_app_saml"&lt;/span&gt; &lt;span class="s2"&gt;"redshift"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Redshift Query Editor v2"&lt;/span&gt;
  &lt;span class="nx"&gt;logo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${path.module}/images/redshift.png"&lt;/span&gt;
  &lt;span class="nx"&gt;preconfigured_app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"amazon_aws"&lt;/span&gt;
  &lt;span class="nx"&gt;saml_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"2.0"&lt;/span&gt;
  &lt;span class="nx"&gt;default_relay_state&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://${data.aws_region.current.name}.console.aws.amazon.com/sqlworkbench/home"&lt;/span&gt;

  &lt;span class="nx"&gt;app_settings_json&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jsonencode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="s2"&gt;"awsEnvironmentType"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"aws.amazon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"appFilter"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"okta"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"groupFilter"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"(?{{role}}[a-zA-Z0-9+=,.@&lt;/span&gt;&lt;span class="err"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;-_]+)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"joinAllRoles"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"loginURL"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"https://console.aws.amazon.com/ec2/home"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"roleValuePattern"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:iam::${data.aws_caller_identity.current.account_id}:saml-provider/OktaRedshiftFederation,${aws_iam_role.default.arn}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"sessionDuration"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"useGroupMapping"&lt;/span&gt; &lt;span class="err"&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="nx"&gt;attribute_statements&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"EXPRESSION"&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;"https://aws.amazon.com/SAML/Attributes/PrincipalTag:RedshiftDbUser"&lt;/span&gt;
    &lt;span class="nx"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"&lt;/span&gt;
    &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"user.username"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;attribute_statements&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"EXPRESSION"&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;"https://aws.amazon.com/SAML/Attributes/PrincipalTag:RedshiftDbGroups"&lt;/span&gt;
    &lt;span class="nx"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"&lt;/span&gt;
    &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"String.join(&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, isMemberOfGroupName(&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;datascientist&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;) ? 'datascientist' : '',isMemberOfGroupName(&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;admin&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;) ? 'admin' : '')"&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="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"okta_app_group_assignments"&lt;/span&gt; &lt;span class="s2"&gt;"redshift"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;app_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;okta_app_saml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redshift&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;id&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="nx"&gt;okta_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;datascientist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;id&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="nx"&gt;okta_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;
  
  
  Create IAM SAML Provider Role
&lt;/h3&gt;

&lt;p&gt;After setting up the Okta application, create the IAM SAML provider to establish a trust relationship between Okta and AWS using the Okta metadata.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_saml_provider"&lt;/span&gt; &lt;span class="s2"&gt;"redshift_okta"&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;"OktaRedshiftFederation"&lt;/span&gt;
  &lt;span class="nx"&gt;saml_metadata_document&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;okta_app_saml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redshift&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev"&lt;/span&gt;
    &lt;span class="nx"&gt;stack&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"redshift"&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;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this blog post, we demonstrated how to securely federate SSO access to AWS Redshift Query Editor v2 using Okta as the identity provider, leveraging Terraform for seamless infrastructure management. By creating the necessary IAM roles and configuring the Okta SAML application, we established a robust trust relationship between Okta and AWS. This setup not only simplifies user access to Redshift Query Editor v2 but also enhances security by eliminating the need to share database users credentials. With this integration, your teams can efficiently explore, share, and collaborate on data, driving insightful decisions and streamlined operations.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>queryeditor</category>
      <category>okta</category>
      <category>redshift</category>
    </item>
    <item>
      <title>Enabling Cross-Account Access for AWS Lake Formation with Data Filters Using Terraform</title>
      <dc:creator>Thulasiraj Komminar</dc:creator>
      <pubDate>Fri, 17 May 2024 20:34:26 +0000</pubDate>
      <link>https://dev.to/aws-builders/enabling-cross-account-access-for-lake-formation-with-data-filters-using-terraform-38d1</link>
      <guid>https://dev.to/aws-builders/enabling-cross-account-access-for-lake-formation-with-data-filters-using-terraform-38d1</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In my &lt;a href="https://thulasirajkomminar.com/lake-formation-cross-account-access-using-terraform-e21279e30531"&gt;previous blog&lt;/a&gt;, we explored enabling cross-account data sharing using AWS Lake Formation with Terraform. In this post, we’ll dive deeper into enhancing that setup with data filters. Lake Formation data filtering allows for column-level, row-level, and cell-level security. This blog will focus specifically on implementing cell-level security to fine-tune data access controls.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QhNVm6wo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A3Mw7Qu1EaNPuXGGPIfdqOg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QhNVm6wo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A3Mw7Qu1EaNPuXGGPIfdqOg.jpeg" alt="" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Designed by Freepik&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Data filter levels
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Column-level&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Granting permissions on a Data Catalog table with column-level filtering allows users to view only specific columns and nested columns they have access to. This enables defining security policies that grant access to partial sub-structures of nested columns.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Row-level&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Granting permissions on a Data Catalog table with row-level filtering allows users to view only specific rows of data they have access to. Filtering is based on the values of one or more columns, and nested column structures can be included in row-filter expressions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cell-level&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cell-level security combines both row and column filtering, providing a highly flexible permissions model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Data Filter in the Source Account
&lt;/h3&gt;

&lt;p&gt;Assuming you have already followed the Lake Formation setup in Source Account as detailed in my &lt;a href="https://thulasirajkomminar.com/lake-formation-cross-account-access-using-terraform-e21279e30531"&gt;previous blog&lt;/a&gt;, we can now proceed with creating the data filter. Let’s use an example involving IIoT measurements. Suppose you have equipment spread across multiple sites and need to grant specific IAM roles access to particular sites and columns. Here’s how to achieve this using Terraform:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lHtse5Pi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:4800/format:webp/1%2A1MzDkwuH2SRbckk0H7k4GA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lHtse5Pi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:4800/format:webp/1%2A1MzDkwuH2SRbckk0H7k4GA.png" alt="" width="800" height="858"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define Local Configuration: The &lt;strong&gt;&lt;code&gt;filter_config&lt;/code&gt;&lt;/strong&gt; variable lists the sites, columns, and IAM roles in the target account that need access.&lt;/li&gt;
&lt;li&gt;Retrieve AWS Account ID: The &lt;code&gt;aws_caller_identity&lt;/code&gt; data source fetches the current AWS account ID.&lt;/li&gt;
&lt;li&gt;Create Data Cell Filters: The &lt;code&gt;aws_lakeformation_data_cells_filter&lt;/code&gt; resource iterates over the &lt;strong&gt;&lt;code&gt;filter_config&lt;/code&gt;&lt;/strong&gt; to create the necessary filters for each IAM role.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This setup ensures that specific IAM roles have access only to the defined sites and columns, enhancing security and data management.&lt;/p&gt;

&lt;h3&gt;
  
  
  Share Catalog with Target Account
&lt;/h3&gt;

&lt;p&gt;Now that we’ve created the data filter, let’s utilize it while sharing the catalog. In the code snippet below, we’ll share the database and table with the target account. Note that when sharing the table, we’ll include the data filter created in the previous step.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mKZ-i4_r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AK7W1674LddBfQwGxBreSYg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mKZ-i4_r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AK7W1674LddBfQwGxBreSYg.png" alt="" width="800" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this snippet:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Share Database Permissions: The &lt;code&gt;aws_lakeformation_permissions&lt;/code&gt; resource shares the &lt;strong&gt;&lt;code&gt;IIoTDataLake&lt;/code&gt;&lt;/strong&gt; database with the target account and grants the &lt;code&gt;DESCRIBE&lt;/code&gt; permission.&lt;/li&gt;
&lt;li&gt;Share Table Permissions: Similarly, the resource shares the &lt;strong&gt;&lt;code&gt;measurements&lt;/code&gt;&lt;/strong&gt; table with the target account, granting the &lt;code&gt;SELECT&lt;/code&gt; permission. It also includes the data filter created earlier, ensuring that the target account only accesses the filtered data according to the defined criteria.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With this setup, you can securely share specific data from your catalog with the target account, ensuring compliance and data integrity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Resource Link in Target Account for Access
&lt;/h3&gt;

&lt;p&gt;After sharing the catalog and table with a data filter to the target account, let’s proceed to the target account to establish a resource link for accessing the shared catalog data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AstOJ0hK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:4800/format:webp/1%2At3LBvg8kTLKfuZ8iDfrJRA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AstOJ0hK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:4800/format:webp/1%2At3LBvg8kTLKfuZ8iDfrJRA.png" alt="" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create Resource Link: The &lt;code&gt;aws_glue_catalog_database&lt;/code&gt; resource establishes a database resource link named &lt;strong&gt;&lt;code&gt;IIoTDataLake-Target&lt;/code&gt;&lt;/strong&gt; in the target account. It links to the &lt;strong&gt;&lt;code&gt;IIoTDataLake&lt;/code&gt;&lt;/strong&gt; database in the source account, enabling access to the shared catalog data.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By creating this resource link, you enable seamless access to the shared data catalog from the target account, facilitating data utilization and analysis across accounts while maintaining security and compliance measures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Granting Permissions for IAM Roles
&lt;/h3&gt;

&lt;p&gt;Now that we’ve created the resource link, we can grant access to the resource link and the shared catalog. After this step, the IAM roles will have access to the filtered data shared from the source account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zHF8z16k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:4800/format:webp/1%2AexBKi_t4N8qE8hvjjRF-jg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zHF8z16k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:4800/format:webp/1%2AexBKi_t4N8qE8hvjjRF-jg.png" alt="" width="800" height="684"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this configuration:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Grant Database Permissions: The &lt;code&gt;aws_lakeformation_permissions&lt;/code&gt; resource grants the DESCRIBE permission to the IAM roles for the &lt;strong&gt;&lt;code&gt;IIoTDataLake-Target&lt;/code&gt;&lt;/strong&gt; database in the target account. This allows the roles to describe the database structure and metadata.&lt;/li&gt;
&lt;li&gt;Grant Table Permissions: Similarly, the resource grants the &lt;code&gt;SELECT&lt;/code&gt; permission to the IAM roles for the &lt;strong&gt;&lt;code&gt;measurements&lt;/code&gt;&lt;/strong&gt; table in the shared catalog. This enables the roles to select and read data from the table.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With these permissions granted, the IAM roles now have access to the filtered data shared from the source account, allowing for seamless data analysis and utilization within the target account.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this blog, we’ve delved into the intricacies of cross-account data sharing using AWS Lake Formation and Terraform. By implementing data filters and establishing resource links, we’ve ensured secure access to shared data while maintaining granular control over permissions. This streamlined approach facilitates collaborative data analysis across accounts, empowering teams to derive insights effectively while upholding data security and compliance standards.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/lake-formation/latest/dg/data-filtering.html"&gt;Data filtering and cell-level security in Lake Formation — AWS Lake Formation (amazon.com)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>awslakeformation</category>
      <category>terraform</category>
      <category>aws</category>
      <category>awscrossaccount</category>
    </item>
    <item>
      <title>How to Write Data to InfluxDB v3 with GoLang: A Step-by-Step Tutorial</title>
      <dc:creator>Thulasiraj Komminar</dc:creator>
      <pubDate>Tue, 14 May 2024 15:04:59 +0000</pubDate>
      <link>https://dev.to/thulasirajkomminar/how-to-write-data-to-influxdb-v3-with-golang-a-step-by-step-tutorial-4fhe</link>
      <guid>https://dev.to/thulasirajkomminar/how-to-write-data-to-influxdb-v3-with-golang-a-step-by-step-tutorial-4fhe</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In this blog post, we’ll delve into the process of writing data into InfluxDB v3 using Go. Our focus will be on harnessing the capabilities of the &lt;a href="https://github.com/InfluxCommunity/influxdb3-go/tree/main"&gt;&lt;code&gt;influxdb3-go&lt;/code&gt;&lt;/a&gt; client library, particularly its support for annotated structs. Through a practical example, we’ll demonstrate how to convert a slice into a structured format and efficiently batch write it into InfluxDB.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hwxZe9_U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A-Fs41Z0YJroCGZc6gapO1Q.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hwxZe9_U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A-Fs41Z0YJroCGZc6gapO1Q.jpeg" alt="" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up a Go Project for IIoT Measurements: A Step-by-Step Guide
&lt;/h3&gt;

&lt;p&gt;Let’s kickstart by initializing a Go project named &lt;code&gt;iiot-measurements&lt;/code&gt; and structuring it with three essential files:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;main.go&lt;/code&gt;: Responsible for the main function.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;influxdb3.go&lt;/code&gt;: Contains the struct and functions for InfluxDB writing.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;config.go&lt;/code&gt;: Handles the loading of InfluxDB credentials from the environment.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s how to set up the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir iiot-measurements &amp;amp;&amp;amp; cd iiot-measurements &amp;amp;&amp;amp; go mod init iiot-measurements
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let’s install the latest influxdb3 Go client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go get github.com/InfluxCommunity/influxdb3-go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementing Annotated Structs for InfluxDB Data Writing
&lt;/h3&gt;

&lt;p&gt;With the &lt;code&gt;influxdb3-go&lt;/code&gt; client, data can be provided in various formats such as &lt;a href="https://docs.influxdata.com/influxdb/cloud-serverless/reference/syntax/line-protocol/"&gt;line protocol&lt;/a&gt;, point, or as a struct. For this tutorial, we’ll opt for the annotated struct approach to ensure a fixed schema. This choice suits scenarios where maintaining a consistent schema is crucial. However, if your use case involves handling dynamic schemas, other options like line protocol or point may be more suitable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z3zvKONo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Ac6ZZYn_9CsssbQZfMhuoNg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z3zvKONo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Ac6ZZYn_9CsssbQZfMhuoNg.png" alt="" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Loading InfluxDB Credentials from Environment Variables
&lt;/h3&gt;

&lt;p&gt;Before instantiating the InfluxDB client, it’s essential to load the credentials from the environment. To achieve this, we’ll utilize the &lt;code&gt;env&lt;/code&gt; package to parse environment variables into our &lt;code&gt;InfluxdbConfig&lt;/code&gt; struct. Additionally, we’ll create a &lt;code&gt;NewConfig()&lt;/code&gt; function to facilitate the instantiation of the struct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go get github.com/caarlos0/env/v11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f7DskF9B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AC1Rdnn_nFZbWZxb21ORiPw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f7DskF9B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AC1Rdnn_nFZbWZxb21ORiPw.png" alt="" width="800" height="766"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Instantiating the InfluxDB Client
&lt;/h3&gt;

&lt;p&gt;After loading the credentials, the next step is to create a function that instantiates the InfluxDB client. We’ll define a &lt;code&gt;NewClient()&lt;/code&gt; function responsible for this task, utilizing the configuration struct previously defined. This function ensures seamless creation of the client with the provided configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NkE-XudG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AYv66INhYQWhBN8vodKAD1w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NkE-XudG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AYv66INhYQWhBN8vodKAD1w.png" alt="" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing Batch Write Function for InfluxDB Data
&lt;/h3&gt;

&lt;p&gt;After setting up the InfluxDB client instantiation, the next step is to implement a function for batch writing data to InfluxDB v3. We’ll create a function named &lt;code&gt;BatchWrite()&lt;/code&gt; responsible for this task. This function will take a slice of annotated Measurement structs and convert them into an &lt;code&gt;[]interface{}&lt;/code&gt; format, facilitating batch writing to InfluxDB v3.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HyRHixH4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AJKaNGjRNtb_puB6Xr7iUBg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HyRHixH4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AJKaNGjRNtb_puB6Xr7iUBg.png" alt="" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing Data to InfluxDB v3
&lt;/h3&gt;

&lt;p&gt;With all the required functions in place, we are now ready to instantiate the client and write a slice of data to InfluxDB v3. First, we’ll initialize the client using the configuration obtained from environment variables. Then, we’ll utilize the &lt;code&gt;BatchWrite()&lt;/code&gt; function to efficiently write the data as a batch to InfluxDB.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5viywUxn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AWcodBT6Eqw7yNyZVN-myEw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5viywUxn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AWcodBT6Eqw7yNyZVN-myEw.png" alt="" width="800" height="1148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Exploring Data
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TrA00xn7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AlyPdv4MgNYTtEgPZKz2DoQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TrA00xn7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AlyPdv4MgNYTtEgPZKz2DoQ.png" alt="" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this tutorial, we’ve explored the process of writing data to InfluxDB v3 using GoLang and the &lt;code&gt;influxdb3-go&lt;/code&gt; client library. By leveraging annotated structs and environment-based configuration loading, we’ve established a robust foundation for efficiently managing InfluxDB data within Go applications.&lt;/p&gt;

&lt;p&gt;We began by setting up a Go project and initializing the InfluxDB client with credentials loaded from environment variables. Through the implementation of a &lt;code&gt;BatchWrite()&lt;/code&gt; function, we demonstrated how to streamline the process of writing data in batches to InfluxDB v3.&lt;/p&gt;

&lt;p&gt;By following the steps outlined in this tutorial, you’re now equipped with the knowledge to seamlessly integrate InfluxDB data writing capabilities into your Go applications, ensuring reliability and scalability for your time-series data management needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/komminarlabs/iiot-measurements-influxdb3"&gt;https://github.com/komminarlabs/iiot-measurements-influxdb3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/InfluxCommunity/influxdb3-go/blob/main/README.md"&gt;influxdb3-go/README.md at main · InfluxCommunity/influxdb3-go (github.com)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.influxdata.com/influxdb/cloud-serverless/reference/syntax/line-protocol/"&gt;Line protocol | InfluxDB Cloud Serverless Documentation (influxdata.com)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>influxdbv3</category>
      <category>v3</category>
      <category>influxdb</category>
      <category>iiot</category>
    </item>
    <item>
      <title>How to bridge a Terraform Provider to Pulumi</title>
      <dc:creator>Thulasiraj Komminar</dc:creator>
      <pubDate>Fri, 15 Mar 2024 23:49:16 +0000</pubDate>
      <link>https://dev.to/thulasirajkomminar/how-to-bridge-a-terraform-provider-to-pulumi-41c5</link>
      <guid>https://dev.to/thulasirajkomminar/how-to-bridge-a-terraform-provider-to-pulumi-41c5</guid>
      <description>&lt;h3&gt;
  
  
  Introduction:
&lt;/h3&gt;

&lt;p&gt;In this blog post, we’ll delve into the process of creating a &lt;a href="https://www.pulumi.com/docs/concepts/resources/providers/"&gt;Pulumi Resource provider&lt;/a&gt; sourced from a Terraform Provider developed with the &lt;a href="https://developer.hashicorp.com/terraform/plugin/framework"&gt;Terraform Plugin Framework&lt;/a&gt;. Our focus will be on leveraging the &lt;a href="https://github.com/pulumi/pulumi-terraform-bridge"&gt;bridge package&lt;/a&gt; to facilitate this transition seamlessly. To illustrate, we’ll demonstrate bridging the &lt;a href="https://registry.terraform.io/providers/komminarlabs/influxdb/latest"&gt;InfluxDB Terraform provider&lt;/a&gt; to Pulumi.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jmK_D8P7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AS_2Md9h9VwF04yC1LIfGwQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jmK_D8P7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AS_2Md9h9VwF04yC1LIfGwQ.png" alt="" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites:
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Before delving further, it’s essential to possess a foundational understanding of &lt;a href="https://developer.hashicorp.com/terraform/language/providers"&gt;Terraform providers&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/concepts/resources/providers/"&gt;Pulumi resource providers&lt;/a&gt;, and &lt;a href="https://www.influxdata.com/"&gt;InfluxDB&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ensure the following tools are installed and present in your &lt;code&gt;%PATH&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/pulumi/pulumictl#installation"&gt;pulumictl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://golang.org/dl/"&gt;Go 1.17&lt;/a&gt; or latest&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/en/"&gt;NodeJS&lt;/a&gt; 14.x&lt;/li&gt;
&lt;li&gt;&lt;a href="https://yarnpkg.com/"&gt;Yarn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.python.org/downloads/"&gt;Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dotnet.microsoft.com/download"&gt;.NET&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why Bridge a Terraform Provider to Pulumi:
&lt;/h3&gt;

&lt;p&gt;The mature and vibrant Terraform Providers ecosystem benefits from contributions by numerous industry leaders in cloud and infrastructure. By bridging Terraform Providers to Pulumi, organizations gain access to reliable and battle-tested infrastructure management capabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  How the bridge works:
&lt;/h3&gt;

&lt;p&gt;The bridge operates across two significant phases: design-time and runtime.&lt;/p&gt;

&lt;p&gt;During design-time, the bridge meticulously examines the schema of a Terraform Provider. However, it’s important to note that this process is applicable solely to providers constructed with static schemas.&lt;/p&gt;

&lt;p&gt;Moving on to the runtime phase, the bridge establishes a connection between the Pulumi engine and the designated Terraform Provider by harnessing Pulumi’s RPC interfaces. This interaction heavily relies on the Terraform provider schema, facilitating tasks such as validation and the computation of differences.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to bridge a provider:
&lt;/h3&gt;

&lt;p&gt;Pulumi provides two options for initializing your project: you can either utilize the template repository offered by Pulumi, or opt for the community-supported &lt;a href="https://github.com/tmeckel/pulumi-tf-provider-cookiecutter"&gt;cookiecutter template&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you choose the cookiecutter template, setting up an initial version is straightforward — just specify a few configuration settings. However, if you prefer the template repository route, follow the steps outlined below to get started:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To begin, navigate to the template repository and select &lt;em&gt;Use this template&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Then, ensure the following options are configured:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Owner&lt;/strong&gt; : Your GitHub organization or username.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository name&lt;/strong&gt; : Preface your repository name with &lt;em&gt;pulumi&lt;/em&gt; as per standard practice. For instance, &lt;code&gt;pulumi-influxdb&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description&lt;/strong&gt; : Provide a brief description of your provider.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository type&lt;/strong&gt; : Set it to Public.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;After configuring these options, proceed to clone the generated repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Execute the following command to update the files, replacing placeholders with the name of your provider.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make prepare &lt;span class="nv"&gt;NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;influxdb &lt;span class="nv"&gt;REPOSITORY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;github.com/komminarlabs/pulumi-influxdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rename folders in &lt;code&gt;provider/cmd&lt;/code&gt; to &lt;code&gt;pulumi-resource-influxdb&lt;/code&gt; and &lt;code&gt;pulumi-tfgen-influxdb&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Replace dependencies in &lt;code&gt;provider/go.mod&lt;/code&gt; to reflect your repository name.&lt;/li&gt;
&lt;li&gt;Find and replace all instances of the boilerplate xyz with the NAME of your provider.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Ensure to accurately set your GitHub organization or username in all files where your provider is referenced as a dependency.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;examples/go.mod&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;provider/resources.go&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sdk/go.mod&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;provider/cmd/pulumi-resource-influxdb/main.go&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;provider/cmd/pulumi-tfgen-influxdb/main.go&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Create a Shim
&lt;/h4&gt;

&lt;p&gt;Although the New() provider function resides within an internal package, referencing it in an external Go project isn’t straightforward. However, it’s still achievable through Go linker techniques.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;code&gt;provider/shim&lt;/code&gt; directory.
&lt;/li&gt;
&lt;/ol&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;provider/shim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Add a &lt;code&gt;go.mod&lt;/code&gt; file with the following content.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;komminarlabs&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;terraform&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;influxdb&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;shim&lt;/span&gt;

&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="m"&gt;1.22&lt;/span&gt;

&lt;span class="n"&gt;require&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;hashicorp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;terraform&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;framework&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="m"&gt;.6.0&lt;/span&gt;
 &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;komminarlabs&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;terraform&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;influxdb&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="m"&gt;.0.1&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Add a &lt;code&gt;shim.go&lt;/code&gt; file with the following content.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;shim&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="n"&gt;tfpf&lt;/span&gt; &lt;span class="s"&gt;"github.com/hashicorp/terraform-plugin-framework/provider"&lt;/span&gt;
 &lt;span class="s"&gt;"github.com/komminarlabs/terraform-provider-influxdb/internal/provider"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewProvider&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;tfpf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&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="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"dev"&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;h4&gt;
  
  
  Import the New Shim Provider
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;provider/resources.go&lt;/code&gt; import the shim package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;influxdb&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="s"&gt;"fmt"&lt;/span&gt;
 &lt;span class="s"&gt;"path"&lt;/span&gt;

 &lt;span class="c"&gt;// Allow embedding bridge-metadata.json in the provider.&lt;/span&gt;
 &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="s"&gt;"embed"&lt;/span&gt;

 &lt;span class="n"&gt;influxdbshim&lt;/span&gt; &lt;span class="s"&gt;"github.com/komminarlabs/terraform-provider-influxdb/shim"&lt;/span&gt;

 &lt;span class="n"&gt;pf&lt;/span&gt; &lt;span class="s"&gt;"github.com/pulumi/pulumi-terraform-bridge/pf/tfbridge"&lt;/span&gt;
 &lt;span class="s"&gt;"github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge"&lt;/span&gt;
 &lt;span class="s"&gt;"github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge/tokens"&lt;/span&gt;
 &lt;span class="n"&gt;shim&lt;/span&gt; &lt;span class="s"&gt;"github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim"&lt;/span&gt;
 &lt;span class="s"&gt;"github.com/pulumi/pulumi/sdk/v3/go/common/resource"&lt;/span&gt;

 &lt;span class="c"&gt;// Import custom shim&lt;/span&gt;
 &lt;span class="s"&gt;"github.com/komminarlabs/pulumi-influxdb/provider/pkg/version"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Instantiate the Shim Provider
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;provider/resources.go&lt;/code&gt;, replace &lt;code&gt;shimv2.NewProvider(influxdb.Provider())&lt;/code&gt; with &lt;code&gt;pf.ShimProvider(influxdbshim.NewProvider())&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;tfbridge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProviderInfo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;prov&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tfbridge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProviderInfo&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// Instantiate the Terraform provider&lt;/span&gt;
  &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShimProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;influxdbshim&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewProvider&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;Edit &lt;code&gt;provider/go.mod&lt;/code&gt; and add &lt;code&gt;github.com/komminarlabs/terraform-provider-influxdb/shim v0.0.0&lt;/code&gt; to the requirements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;komminarlabs&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;influxdb&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt;

&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="m"&gt;1.22&lt;/span&gt;

&lt;span class="n"&gt;replace&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;hashicorp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;terraform&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sdk&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;terraform&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sdk&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="m"&gt;.0.0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;20240202163305&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e2a20ae13ef9&lt;/span&gt;
 &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;komminarlabs&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;terraform&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;influxdb&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;shim&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;shim&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;require&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;komminarlabs&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;terraform&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;influxdb&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;shim&lt;/span&gt; &lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="m"&gt;.0.0&lt;/span&gt;
 &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;terraform&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bridge&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pf&lt;/span&gt; &lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="m"&gt;.29.0&lt;/span&gt;
 &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;terraform&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bridge&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v3&lt;/span&gt; &lt;span class="n"&gt;v3&lt;/span&gt;&lt;span class="m"&gt;.76.0&lt;/span&gt;
 &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sdk&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v3&lt;/span&gt; &lt;span class="n"&gt;v3&lt;/span&gt;&lt;span class="m"&gt;.108.1&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Build the Provider:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Build Generator
&lt;/h4&gt;

&lt;p&gt;Create the schema by running 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;make tfgen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Add Mappings
&lt;/h4&gt;

&lt;p&gt;In this section we will add the mappings that allow the interoperation between the Pulumi provider and the Terraform provider. Terraform resources map to an identically named concept in Pulumi. Terraform data sources map to plain old functions in your supported programming language of choice.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Resource mapping&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For every resource present in the provider, include an entry in the Resources property of the tfbridge.ProviderInfo structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;Resources&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tfbridge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceInfo&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s"&gt;"influxdb_authorization"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Tok&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tfbridge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MakeResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mainPkg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mainMod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;
   &lt;span class="s"&gt;"influxdb_bucket"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Tok&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tfbridge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MakeResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mainPkg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mainMod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Bucket"&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;
   &lt;span class="s"&gt;"influxdb_organization"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Tok&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tfbridge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MakeResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mainPkg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mainMod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Organization"&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;ul&gt;
&lt;li&gt;&lt;strong&gt;Data Source mapping&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add an entry in the DataSources property of the &lt;code&gt;tfbridge.ProviderInfo&lt;/code&gt; for each data source included in the provider.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;DataSources&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tfbridge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataSourceInfo&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s"&gt;"influxdb_authorization"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Tok&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tfbridge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MakeDataSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mainPkg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mainMod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"getAuthorization"&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;
   &lt;span class="s"&gt;"influxdb_authorizations"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Tok&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tfbridge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MakeDataSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mainPkg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mainMod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"getAuthorizations"&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;
   &lt;span class="s"&gt;"influxdb_bucket"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Tok&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tfbridge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MakeDataSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mainPkg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mainMod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"getBucket"&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;
   &lt;span class="s"&gt;"influxdb_buckets"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Tok&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tfbridge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MakeDataSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mainPkg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mainMod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"getBuckets"&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;
   &lt;span class="s"&gt;"influxdb_organization"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Tok&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tfbridge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MakeDataSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mainPkg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mainMod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"getOrganization"&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;
   &lt;span class="s"&gt;"influxdb_organizations"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Tok&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tfbridge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MakeDataSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mainPkg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mainMod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"getOrganizations"&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;h4&gt;
  
  
  Build Provider
&lt;/h4&gt;

&lt;p&gt;Generate the provider binary by executing 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;make provider
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Build SDKs
&lt;/h4&gt;

&lt;p&gt;Compile the SDKs across the range of languages supported by Pulumi, and validate that the provider code adheres to the Go language standards.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make build_sdks

make lint_provider
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Write documentation:
&lt;/h3&gt;

&lt;p&gt;Incorporate a &lt;code&gt;docs/&lt;/code&gt; directory containing template pages that correspond to the different tabs typically found on a package page within the Pulumi Registry.&lt;/p&gt;

&lt;h4&gt;
  
  
  Overview, installation, &amp;amp; configuration
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;_index.md&lt;/code&gt;, which will be displayed on the Overview tab for your package in the Pulumi Registry. The title of this page should align with the package display name, serving as the heading shown on the package detail page. The Overview section is an ideal space to include a concise description of your package’s functionality along with a straightforward example.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;InfluxDB&lt;/span&gt;
&lt;span class="na"&gt;meta_desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Provides an overview of the InfluxDB Provider for Pulumi.&lt;/span&gt;
&lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;package&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;installation-configuration.md&lt;/code&gt;, this file will be displayed on your package’s Installation &amp;amp; Configuration tab in the Pulumi Registry. Utilize this page to provide comprehensive instructions on setting up your package, covering aspects such as authentication procedures. Additionally, include a list of configuration options available for use with your package.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;InfluxDB Installation &amp;amp; Configuration&lt;/span&gt;
&lt;span class="na"&gt;meta_desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Information on how to install the InfluxDB provider.&lt;/span&gt;
&lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;package&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Publish your package:
&lt;/h3&gt;

&lt;p&gt;After authoring and thoroughly testing your package locally, the next step is to publish it to make it accessible to the Pulumi community. This process involves publishing several artifacts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The npm, NuGet, Java, and Python SDK packages to the &lt;a href="https://npmjs.com/"&gt;npm Registry&lt;/a&gt;, the &lt;a href="https://nuget.org/"&gt;NuGet Gallery&lt;/a&gt;, &lt;a href="https://central.sonatype.com/"&gt;Maven Central&lt;/a&gt; and the &lt;a href="https://pypi.org/"&gt;Python Package Index&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The Go module to your Git repository, by adding a tag.&lt;/li&gt;
&lt;li&gt;The binary Pulumi resource provider plugin to a binary hosting provider of your choice.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To streamline this process, we’ll leverage GitHub Actions. Below are the GitHub Actions you’ll use for this purpose.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;v*.*.*&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
  &lt;span class="na"&gt;NODE_AUTH_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.NPM_TOKEN }}&lt;/span&gt;
  &lt;span class="na"&gt;NPM_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.NPM_TOKEN }}&lt;/span&gt;
  &lt;span class="na"&gt;PUBLISH_NPM&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;NPM_REGISTRY_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://registry.npmjs.org&lt;/span&gt;
  &lt;span class="na"&gt;NUGET_PUBLISH_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.NUGET_PUBLISH_KEY }}&lt;/span&gt;
  &lt;span class="na"&gt;NUGET_FEED_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://api.nuget.org/v3/index.json&lt;/span&gt;
  &lt;span class="na"&gt;PUBLISH_NUGET&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;PYPI_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.PYPI_API_TOKEN }}&lt;/span&gt;
  &lt;span class="na"&gt;PYPI_USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;__token__"&lt;/span&gt;
  &lt;span class="na"&gt;PYPI_REPOSITORY_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
  &lt;span class="na"&gt;PUBLISH_PYPI&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;publish_binary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish Binary&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;fail-fast&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;goversion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;1.22.x&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout Repo&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Unshallow clone for tags&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git fetch --prune --unshallow --tags&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Go&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-go@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;go-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{matrix.goversion}}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install pulumictl&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jaxxstorm/action-install-gh-release@v1.10.0&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pulumi/pulumictl&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set PreRelease Version&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "GORELEASER_CURRENT_TAG=v$(pulumictl get version --language generic)" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run GoReleaser&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;goreleaser/goreleaser-action@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-p 3 release --rm-dist&lt;/span&gt;
          &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;latest&lt;/span&gt;

  &lt;span class="na"&gt;publish_sdk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish SDK&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;publish_binary&lt;/span&gt;
    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;fail-fast&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;dotnetversion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;6.0.x&lt;/span&gt;
        &lt;span class="na"&gt;goversion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;1.22.x&lt;/span&gt;
        &lt;span class="na"&gt;nodeversion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;16.x&lt;/span&gt;
        &lt;span class="na"&gt;pythonversion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.9"&lt;/span&gt;
        &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;nodejs&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;python&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;dotnet&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;go&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout Repo&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Unshallow clone for tags&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git fetch --prune --unshallow --tags&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Go&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-go@v5&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;go-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.goversion }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install pulumictl&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jaxxstorm/action-install-gh-release@v1.11.0&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pulumi/pulumictl&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install pulumi&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pulumi/actions@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.language == 'nodejs'}}&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Node&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{matrix.nodeversion}}&lt;/span&gt;
          &lt;span class="na"&gt;registry-url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{env.NPM_REGISTRY_URL}}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.language == 'dotnet'}}&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup DotNet&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-dotnet@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;dotnet-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{matrix.dotnetversion}}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.language == 'python'}}&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Python&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{matrix.pythonversion}}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build SDK&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;make build_${{ matrix.language }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.language == 'python' &amp;amp;&amp;amp; env.PUBLISH_PYPI == 'true' }}&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish package to PyPI&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pypa/gh-action-pypi-publish@release/v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.PYPI_USERNAME }}&lt;/span&gt;
          &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.PYPI_PASSWORD }}&lt;/span&gt;
          &lt;span class="na"&gt;packages_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{github.workspace}}/sdk/python/bin/dist&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.language == 'nodejs' &amp;amp;&amp;amp; env.PUBLISH_NPM == 'true' }}&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;JS-DevTools/npm-publish@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;access&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;public"&lt;/span&gt;
          &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.NPM_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;package&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{github.workspace}}/sdk/nodejs/bin/package.json&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.language == 'dotnet' &amp;amp;&amp;amp; env.PUBLISH_NUGET == 'true' }}&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;publish nuget package&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;dotnet nuget push ${{github.workspace}}/sdk/dotnet/bin/Debug/*.nupkg -s ${{ env.NUGET_FEED_URL }} -k ${{ env.NUGET_PUBLISH_KEY }}&lt;/span&gt;
          &lt;span class="s"&gt;echo "done publishing packages"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Publish the documentation:
&lt;/h3&gt;

&lt;p&gt;To publish your package on the Pulumi Registry, all package documentation is managed through the &lt;a href="https://github.com/pulumi/registry"&gt;pulumi/registry&lt;/a&gt; repository on GitHub. Here’s how to proceed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fork and clone the &lt;code&gt;pulumi/registry&lt;/code&gt; repository to your local machine.&lt;/li&gt;
&lt;li&gt;Add your package to the &lt;a href="https://github.com/pulumi/registry/blob/master/community-packages/package-list.json"&gt;community package list&lt;/a&gt; within the repository.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s"&gt;"repoSlug"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"komminarlabs/pulumi-influxdb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;"schemaFile"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"provider/cmd/pulumi-resource-influxdb/schema.json"&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;After making the necessary changes to add your package to the community package list, open a pull request with the modifications. Subsequently, await review from a member of the Pulumi team.&lt;/li&gt;
&lt;li&gt;Upon review, a Pulumi employee will collaborate with you to finalize the steps required for publishing your Pulumi Package.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Using the provider:
&lt;/h3&gt;

&lt;p&gt;Now that we have successfully built and published our Pulumi provider, let’s proceed to utilize it for resource creation. In this instance, we’ll opt for Python as our preferred programming language.&lt;/p&gt;

&lt;h4&gt;
  
  
  Installation
&lt;/h4&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;python-influxdb
&lt;span class="nb"&gt;cd &lt;/span&gt;python-influxdb

&lt;span class="c"&gt;# (Go through the prompts with the default values)&lt;/span&gt;
pulumi new python

&lt;span class="c"&gt;# Use the virtual Python env that Pulumi sets up for you&lt;/span&gt;
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate

&lt;span class="c"&gt;# Install the provider package&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;komminarlabs_influxdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Set up environment
&lt;/h4&gt;

&lt;p&gt;You have the option to configure the provider either through environment variables or by utilizing the &lt;code&gt;Pulumi.dev.yaml&lt;/code&gt; file.&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;export &lt;/span&gt;&lt;span class="nv"&gt;INFLUXDB_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8086"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;INFLUXDB_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"***"&lt;/span&gt;

pulumi config &lt;span class="nb"&gt;set &lt;/span&gt;influxdb:url http://localhost:8086
pulumi config &lt;span class="nb"&gt;set &lt;/span&gt;influxdb:token &lt;span class="k"&gt;***&lt;/span&gt; &lt;span class="nt"&gt;--secret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following contents to the &lt;code&gt;__main__.py&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;A Python Pulumi program&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pulumi&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;komminarlabs_influxdb&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;influxdb&lt;/span&gt;

&lt;span class="n"&gt;organization&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;influxdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Organization&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;IoT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;IoT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;IoT organization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;influxdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signals&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;org_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;organization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signals&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;This is a bucket to store signals&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;retention_period&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;604800&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;Next, execute the pulumi preview command to view a preview of the updates to an existing stack. Follow this by running pulumi up to either create or update the resources within the stack.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P7JIVbRg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AXvmOgh0rjaYJvJlWyguJ6g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P7JIVbRg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AXvmOgh0rjaYJvJlWyguJ6g.png" alt="" width="800" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7xPSl2rz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AVJIqJaWV291o7HGcO8jI_A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7xPSl2rz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AVJIqJaWV291o7HGcO8jI_A.png" alt="" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also view the stacks in Pulumi cloud.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2zWOmpB4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AACcRel0SVRAl4mK141YpGg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2zWOmpB4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AACcRel0SVRAl4mK141YpGg.png" alt="" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/registry/packages/influxdb/"&gt;InfluxDB | Pulumi Registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@thulasirajkomminar/deploying-and-managing-influxdb-resources-with-terraform-8f1c3c5be8ff"&gt;Deploying and Managing InfluxDB Resources with Terraform | by Thulasiraj Komminar | Feb, 2024 | Medium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/komminarlabs/pulumi-influxdb"&gt;komminarlabs/pulumi-influxdb: Pulumi provider for InfluxDB (github.com)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pulumi/pulumi-tf-provider-boilerplate/tree/main"&gt;pulumi/pulumi-tf-provider-boilerplate: Boilerplate code for Terraform provider-backed Pulumi packages (github.com)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>iot</category>
      <category>provider</category>
      <category>influxdb</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Deploying and Managing InfluxDB Resources with Terraform</title>
      <dc:creator>Thulasiraj Komminar</dc:creator>
      <pubDate>Thu, 15 Feb 2024 17:45:23 +0000</pubDate>
      <link>https://dev.to/thulasirajkomminar/deploying-and-managing-influxdb-resources-with-terraform-p21</link>
      <guid>https://dev.to/thulasirajkomminar/deploying-and-managing-influxdb-resources-with-terraform-p21</guid>
      <description>&lt;h3&gt;
  
  
  Introduction:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Terraform is a powerful infrastructure as code tool that automates cloud infrastructure provisioning and management through simple configuration files. If you’re interested in learning more, I’ve written a short &lt;a href="https://thulasirajkomminar.com/what-is-hashicorp-terraform-42d419a61cb9"&gt;blog&lt;/a&gt; outlining some key components of Terraform.&lt;/li&gt;
&lt;li&gt;InfluxDB is a specialized time-series database tailored for efficiently handling large volumes of time-stamped data. In this blog, we’ll explore how to leverage Terraform for provisioning and managing resources within InfluxDB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WqYki6N0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A8wpyVg6vy_4xqzZwpYMu6g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WqYki6N0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A8wpyVg6vy_4xqzZwpYMu6g.png" alt="" width="800" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites:
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;To install Terraform, you can easily follow the steps outlined in this blog post: &lt;a href="https://developer.hashicorp.com/terraform/install"&gt;Install Terraform&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before diving in, ensure you have a basic understanding of InfluxDB and its components. For installation guidance, refer to this resource: &lt;a href="https://docs.influxdata.com/influxdb/v2/install/"&gt;Install InfluxDB&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Provider Configuration:
&lt;/h3&gt;

&lt;p&gt;To create and manage InfluxDB resources using Terraform, it utilizes specialized plugins known as providers to interface with InfluxDB. I’ve developed and published a provider for InfluxDB on the &lt;a href="https://registry.terraform.io/providers/komminarlabs/influxdb/latest"&gt;Terraform registry&lt;/a&gt;, enabling seamless resource creation and management.&lt;/p&gt;

&lt;p&gt;Let’s begin by configuring the provider.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a file named &lt;code&gt;versions.tf&lt;/code&gt; and insert the following code to declare the InfluxDB provider. This allows Terraform to install and utilize the provider. Provider dependencies are specified within a &lt;code&gt;required_providers&lt;/code&gt; block.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;influxdb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"komminarlabs/influxdb"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1.0.0"&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;ul&gt;
&lt;li&gt;Create another file named &lt;code&gt;main.tf&lt;/code&gt; to initialize the InfluxDB provider. We’ll use a provider block to configure it. You can specify the provider configuration using arguments such as url and token, or alternatively, utilize environment variables like &lt;code&gt;INFLUXDB_TOKEN&lt;/code&gt; and &lt;code&gt;INFLUXDB_URL&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;INFLUXDB_TOKEN&lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"influxdb-token"&lt;/span&gt;
&lt;span class="nx"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;INFLUXDB_URL&lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8086"&lt;/span&gt;

&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"influxdb"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"influxdb-token"&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;"http://localhost:8086"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating and Managing InfluxDB Resources:
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://registry.terraform.io/providers/komminarlabs/influxdb/latest/docs"&gt;komminarlabs/influxdb&lt;/a&gt; provider offers various data sources and resources.&lt;/p&gt;

&lt;h4&gt;
  
  
  Data Sources:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;influxdb_authorization&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;influxdb_authorizations&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;influxdb_bucket&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;influxdb_buckets&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;influxdb_organization&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;influxdb_organizations&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Resources:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;influxdb_authorization&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;influxdb_bucket&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;influxdb_organization&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ll begin by creating resources and then utilize data sources to query the created resources. Let’s create two files: &lt;code&gt;resources.tf&lt;/code&gt; and &lt;code&gt;datasources.tf&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Resources
&lt;/h4&gt;

&lt;p&gt;Resources are the most important element in the Terraform language. Each resource block describes one or more infrastructure objects.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Organization:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An InfluxDB organization is a workspace for a group of users. All dashboards, tasks, buckets, members, etc., belong to an organization. Add the following code to create our organisation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"influxdb_organization"&lt;/span&gt; &lt;span class="s2"&gt;"iot"&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;"IoT"&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"An IoT organization"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running a Terraform plan and verifying everything looks good, let’s proceed with applying the changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hc1aoBz9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AzICyNzJKVX8mMZQbzu1PXA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hc1aoBz9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AzICyNzJKVX8mMZQbzu1PXA.png" alt="" width="800" height="308"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Terraform execution plan and apply results&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MrArKqOI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/508/1%2ArRwX8abPvmuf9mLXyBTlKw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MrArKqOI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/508/1%2ArRwX8abPvmuf9mLXyBTlKw.png" alt="" width="508" height="272"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Switch to the new organization in InfluxDB&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Bucket:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An InfluxDB bucket is a named location where time series data is stored. All buckets have a retention period, a duration of time that each data point persists. InfluxDB drops all points with timestamps older than the bucket’s retention period. A bucket belongs to an organization.&lt;/p&gt;

&lt;p&gt;Let’s proceed by creating a bucket named signals with a retention period of 14 days (1209600 seconds).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"influxdb_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"signals"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;org_id&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;influxdb_organization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;iot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;"signals"&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"This is a bucket to store signals"&lt;/span&gt;
  &lt;span class="nx"&gt;retention_period&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1209600&lt;/span&gt;
&lt;span class="p"&gt;}&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--_WF2ICDt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AF0XJxEGm__3v6HspIie2-Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_WF2ICDt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AF0XJxEGm__3v6HspIie2-Q.png" alt="" width="800" height="335"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Terraform execution plan and apply results&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fwTb2UTk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ANpj8M3_QTqNcAZmFBsE47A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fwTb2UTk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ANpj8M3_QTqNcAZmFBsE47A.png" alt="" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Authorization:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Authorizations are InfluxDB Read/Write API tokens that grants read access, write access, or both to specific buckets in an organization.&lt;/p&gt;

&lt;p&gt;In the following step, we will generate an authorization that enables both read and write access to the bucket established in the prior phase.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"influxdb_authorization"&lt;/span&gt; &lt;span class="s2"&gt;"signals_rw"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;org_id&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;influxdb_organization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;iot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Read &amp;amp; Write access signals bucket"&lt;/span&gt;

  &lt;span class="nx"&gt;permissions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="nx"&gt;action&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"read"&lt;/span&gt;
    &lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;id&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;influxdb_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
      &lt;span class="nx"&gt;org_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;influxdb_organization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;iot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
      &lt;span class="nx"&gt;type&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"buckets"&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="nx"&gt;action&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"write"&lt;/span&gt;
      &lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;id&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;influxdb_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
        &lt;span class="nx"&gt;org_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;influxdb_organization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;iot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
        &lt;span class="nx"&gt;type&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"buckets"&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;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kZl7e17g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AjwPlfb1Yw78DiiMRn7zuqA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kZl7e17g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AjwPlfb1Yw78DiiMRn7zuqA.png" alt="" width="800" height="563"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Terraform execution plan and apply results&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Rv1xiBpW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ATycVtTQiX5aw7pwRF2IryA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Rv1xiBpW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ATycVtTQiX5aw7pwRF2IryA.png" alt="" width="800" height="380"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;API token shown in InfluxDB&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Data Sources
&lt;/h4&gt;

&lt;p&gt;With all the necessary resources created in InfluxDB to manage our time series data, we can now utilize datasources to list all the resources we’ve created.&lt;/p&gt;

&lt;p&gt;A data source is accessed via a special kind of resource known as a data resource, declared using a data block.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"influxdb_organization"&lt;/span&gt; &lt;span class="s2"&gt;"iot"&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;"IoT"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"iot_organization"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;value&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="nx"&gt;influxdb_organization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;iot&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"influxdb_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"signals"&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;"signals"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"signals_bucket"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;value&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="nx"&gt;influxdb_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signals&lt;/span&gt;
&lt;span class="p"&gt;}&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--s8_RP4GJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AYbdFNy-4ap6yu9AfDoawDQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s8_RP4GJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AYbdFNy-4ap6yu9AfDoawDQ.png" alt="" width="800" height="639"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Terraform execution plan and apply results&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://thulasirajkomminar.com/what-is-hashicorp-terraform-42d419a61cb9"&gt;What is HashiCorp Terraform?. Introduction | by Thulasiraj Komminar | Medium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.hashicorp.com/terraform/install"&gt;Install | Terraform | HashiCorp Developer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.influxdata.com/influxdb/v2/install/"&gt;Install InfluxDB | InfluxDB OSS v2 Documentation (influxdata.com)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://registry.terraform.io/providers/komminarlabs/influxdb/latest"&gt;komminarlabs/influxdb | Terraform Registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.hashicorp.com/terraform/language"&gt;Overview — Configuration Language | Terraform | HashiCorp Developer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/komminarlabs/terraform-provider-influxdb/tree/main/examples"&gt;terraform-provider-influxdb/examples at main · komminarlabs/terraform-provider-influxdb (github.com)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion:
&lt;/h3&gt;

&lt;p&gt;Now that we’ve explored how to leverage Terraform for creating and managing InfluxDB resources, it’s time to start utilizing it. If you encounter any bugs or issues while using the provider, be sure to &lt;a href="https://github.com/komminarlabs/terraform-provider-influxdb/issues"&gt;report&lt;/a&gt; them promptly.&lt;/p&gt;

</description>
      <category>provider</category>
      <category>terraform</category>
      <category>iot</category>
      <category>iiot</category>
    </item>
    <item>
      <title>Effortless Infrastructure: Mastering Automated Deployments with Terraform and GitHub Actions</title>
      <dc:creator>Thulasiraj Komminar</dc:creator>
      <pubDate>Fri, 26 Jan 2024 16:39:22 +0000</pubDate>
      <link>https://dev.to/thulasirajkomminar/effortless-infrastructure-mastering-automated-deployments-with-terraform-and-github-actions-23ci</link>
      <guid>https://dev.to/thulasirajkomminar/effortless-infrastructure-mastering-automated-deployments-with-terraform-and-github-actions-23ci</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In the earlier &lt;a href="https://thulasirajkomminar.com/efficient-continuous-deployment-with-github-environments-and-aws-codebuild-9086aef7d913"&gt;blog post&lt;/a&gt;, I showcased the steps to achieve continuous deployment using GitHub Actions and AWS CodeBuild specifically for code deployment. Expanding on those principles, let’s delve into the next phase of our workflow — incorporating infrastructure deployment through Terraform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Wr_0xuQ6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/551/1%2ACFyaoqhfbnwDNHlK4iDzrg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Wr_0xuQ6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/551/1%2ACFyaoqhfbnwDNHlK4iDzrg.png" alt="" width="551" height="420"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Deployment workflow&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Setup Terraform Cloud Workspace:
&lt;/h3&gt;

&lt;p&gt;The GitHub Action you’re about to set up will seamlessly integrate with Terraform Cloud, allowing you to efficiently plan and apply your configurations. Before configuring the Actions workflow, ensure you’ve taken the necessary steps: creating a workspace, incorporating your AWS credentials into your Terraform Cloud workspace, and generating a Terraform Cloud user API token.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Step 1:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;To kickstart the process, initiate a new Terraform Cloud workspace. Navigate to the Projects &amp;amp; Workspaces page, click on &lt;em&gt;New Workspace&lt;/em&gt;, and opt for the &lt;em&gt;API-Driven Workflow&lt;/em&gt; option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IjKWcKZg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AtsAmQCZrOV7PS1tQ4a__HQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IjKWcKZg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AtsAmQCZrOV7PS1tQ4a__HQ.png" alt="" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Step 2:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Provide a name for the workspace and proceed by clicking on the &lt;em&gt;Create&lt;/em&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--COMxhsXH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/590/1%2AQG_sH1EubpjwkwEmAu34OA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--COMxhsXH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/590/1%2AQG_sH1EubpjwkwEmAu34OA.png" alt="" width="590" height="754"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Step 3:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Now, it’s time to include your AWS IAM credentials as environmental variables (&lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt;, &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt;, and &lt;code&gt;AWS_DEFAULT_REGION&lt;/code&gt;) within the workspace. Navigate to the &lt;em&gt;Variables&lt;/em&gt; section in the workspace, click on &lt;em&gt;Add Variable&lt;/em&gt;, and select &lt;em&gt;Environment variable&lt;/em&gt; as the variable category. Terraform Cloud will use these credentials to authenticate to AWS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LzIfeNPJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AP_vMNXFa3teNljhnmm8aBQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LzIfeNPJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AP_vMNXFa3teNljhnmm8aBQ.png" alt="" width="800" height="305"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Step 4:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Now, let’s generate an API token to enable authentication for the Actions workflow in Terraform Cloud. Head to the Tokens page within your Terraform Cloud User Settings. Click on &lt;em&gt;Create an API token&lt;/em&gt;, provide a description, and then click &lt;em&gt;Generate token&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aFqehWyB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/593/1%2AoAUdEX83zmxYuZbGSKfnFw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aFqehWyB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/593/1%2AoAUdEX83zmxYuZbGSKfnFw.png" alt="" width="593" height="344"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Set up a GitHub repository:
&lt;/h3&gt;

&lt;p&gt;Establish a GitHub repository dedicated to housing your infrastructure configuration code and the associated GitHub Actions workflow.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Step 1:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Once you’ve created the repository, proceed to the Settings page. Access the &lt;em&gt;Secrets and Variables&lt;/em&gt; menu, specifically selecting &lt;em&gt;Actions&lt;/em&gt;. Click &lt;em&gt;New Repository Secret&lt;/em&gt; and input the Terraform API token generated in the previous step.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zNL6PTEU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2At6H3XpnwfEv2Ff5czu24aQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zNL6PTEU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2At6H3XpnwfEv2Ff5czu24aQ.png" alt="" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Step 2:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Now, it’s time to incorporate the following GitHub Actions workflow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/komminarlabs/tf-with-github-actions/blob/main/.github/workflows/terraform-plan.yaml"&gt;&lt;strong&gt;Plan&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Terraform'&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;terraform/**&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;modules/**&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;TF_API_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.TF_API_TOKEN }}&lt;/span&gt;
  &lt;span class="na"&gt;TF_WORKING_DIRECTORY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;terraform/&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
  &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;terraform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Plan"&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;defaults&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;working-directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.TF_WORKING_DIRECTORY }}&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hashicorp/setup-terraform@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;cli_config_credentials_token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.TF_API_TOKEN }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Terraform Init&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;init&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git config --global url."https://oauth2:${{ secrets.GITHUB_TOKEN }}@github.com".insteadOf ssh://git@github.com&lt;/span&gt;
          &lt;span class="s"&gt;terraform init&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Terraform Validate&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;validate&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;terraform validate -no-color&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Terraform Plan&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;plan&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;terraform plan -no-color&lt;/span&gt;
        &lt;span class="na"&gt;continue-on-error&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update PR&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/github-script@v7&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;PLAN_OUTPUT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.plan.outputs.stdout }}&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;github-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;// 1. Retrieve existing bot comments for the PR&lt;/span&gt;
            &lt;span class="s"&gt;const { data: comments } = await github.rest.issues.listComments({&lt;/span&gt;
              &lt;span class="s"&gt;owner: context.repo.owner,&lt;/span&gt;
              &lt;span class="s"&gt;repo: context.repo.repo,&lt;/span&gt;
              &lt;span class="s"&gt;issue_number: context.issue.number,&lt;/span&gt;
            &lt;span class="s"&gt;})&lt;/span&gt;
            &lt;span class="s"&gt;const botComment = comments.find(comment =&amp;gt; {&lt;/span&gt;
              &lt;span class="s"&gt;return comment.user.type === 'Bot' &amp;amp;&amp;amp; comment.body.includes('Terraform Plan Results')&lt;/span&gt;
            &lt;span class="s"&gt;})&lt;/span&gt;

            &lt;span class="s"&gt;// 2. Prepare format of the comment&lt;/span&gt;
            &lt;span class="s"&gt;const output = `### Terraform Plan Results 🚀&lt;/span&gt;
            &lt;span class="s"&gt;#### Terraform Initialization ⚙️\`${{ steps.init.outcome }}\`&lt;/span&gt;
            &lt;span class="s"&gt;#### Terraform Validation 🤖\`${{ steps.validate.outcome }}\`&lt;/span&gt;
            &lt;span class="s"&gt;&amp;lt;details&amp;gt;&amp;lt;summary&amp;gt;Validation Output&amp;lt;/summary&amp;gt;&lt;/span&gt;

            &lt;span class="s"&gt;\`\`\`\n&lt;/span&gt;
            &lt;span class="s"&gt;${{ steps.validate.outputs.stdout }}&lt;/span&gt;
            &lt;span class="s"&gt;\`\`\`&lt;/span&gt;

            &lt;span class="s"&gt;&amp;lt;/details&amp;gt;&lt;/span&gt;

            &lt;span class="s"&gt;#### Terraform Plan 📖\`${{ steps.plan.outcome }}\`&lt;/span&gt;

            &lt;span class="s"&gt;&amp;lt;details&amp;gt;&amp;lt;summary&amp;gt;Show Plan&amp;lt;/summary&amp;gt;&lt;/span&gt;

            &lt;span class="s"&gt;\`\`\`\n&lt;/span&gt;
            &lt;span class="s"&gt;${process.env.PLAN_OUTPUT}&lt;/span&gt;
            &lt;span class="s"&gt;\`\`\`&lt;/span&gt;

            &lt;span class="s"&gt;&amp;lt;/details&amp;gt;&lt;/span&gt;

            &lt;span class="s"&gt;*Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`, Working Directory: \`${{ env.TF_WORKING_DIRECTORY }}\`, Workflow: \`${{ github.workflow }}\`*`;&lt;/span&gt;

            &lt;span class="s"&gt;// 3. If we have a comment, update it, otherwise create a new one&lt;/span&gt;
            &lt;span class="s"&gt;if (botComment) {&lt;/span&gt;
              &lt;span class="s"&gt;github.rest.issues.updateComment({&lt;/span&gt;
                &lt;span class="s"&gt;owner: context.repo.owner,&lt;/span&gt;
                &lt;span class="s"&gt;repo: context.repo.repo,&lt;/span&gt;
                &lt;span class="s"&gt;comment_id: botComment.id,&lt;/span&gt;
                &lt;span class="s"&gt;body: output&lt;/span&gt;
              &lt;span class="s"&gt;})&lt;/span&gt;
            &lt;span class="s"&gt;} else {&lt;/span&gt;
              &lt;span class="s"&gt;github.rest.issues.createComment({&lt;/span&gt;
                &lt;span class="s"&gt;issue_number: context.issue.number,&lt;/span&gt;
                &lt;span class="s"&gt;owner: context.repo.owner,&lt;/span&gt;
                &lt;span class="s"&gt;repo: context.repo.repo,&lt;/span&gt;
                &lt;span class="s"&gt;body: output&lt;/span&gt;
              &lt;span class="s"&gt;})&lt;/span&gt;
            &lt;span class="s"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s delve into the deployment job’s steps. We’ve included four key actions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Check out code:&lt;/strong&gt; I’m utilizing a GitHub action to retrieve the code from the repository.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform Init:&lt;/strong&gt; This step utilizes the &lt;code&gt;hashicorp/setup-terraform@v3&lt;/code&gt; action to initialize Terraform. I included the Git configuration in case the code involves private GitHub modules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform Validate:&lt;/strong&gt; This step is dedicated to validating the Terraform code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform Plan:&lt;/strong&gt; This step is employed to execute the Terraform plan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update PR:&lt;/strong&gt; This step leverages the actions/github-script@v7 action to update the Pull Request with the results from the preceding actions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://github.com/komminarlabs/tf-with-github-actions/blob/main/.github/workflows/terraform-apply.yaml"&gt;&lt;strong&gt;Apply&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Terraform'&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;terraform/**&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;modules/**&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;TF_API_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.TF_API_TOKEN }}&lt;/span&gt;
  &lt;span class="na"&gt;TF_WORKING_DIRECTORY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;terraform/&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;terraform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Apply"&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prd&lt;/span&gt;
    &lt;span class="na"&gt;defaults&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;working-directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.TF_WORKING_DIRECTORY }}&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hashicorp/setup-terraform@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;cli_config_credentials_token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.TF_API_TOKEN }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Terraform Init&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;init&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git config --global url."https://oauth2:${{ secrets.GITHUB_TOKEN }}@github.com".insteadOf ssh://git@github.com&lt;/span&gt;
          &lt;span class="s"&gt;terraform init&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Terraform Apply&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apply&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;terraform apply -auto-approve -no-color&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s delve into the steps outlined in this workflow.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Check out code:&lt;/strong&gt; I’m utilizing a GitHub action to retrieve the code from the repository.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform Init:&lt;/strong&gt; This step utilizes the &lt;code&gt;hashicorp/setup-terraform@v3&lt;/code&gt; action to initialize Terraform. Additionally, I’ve included Git configuration in case the code incorporates private GitHub modules. Executing this action is a prerequisite before proceeding with the apply step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform Apply:&lt;/strong&gt; This step applies the Terraform infrastructure configuration to AWS.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Demo
&lt;/h3&gt;

&lt;p&gt;Now, let’s put our setup into action. For demonstration purposes, I’ve included Terraform configuration files to create an S3 bucket.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Pull Request&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;After incorporating the Terraform configuration files into a feature branch, let’s create a pull request to the main branch. This action will initiate GitHub Actions to execute Validation and Plan, with the results seamlessly added back to the pull request for convenient review.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I_fQlPeB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/937/1%2AIbD012o9Yh60jqMQqroZKg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I_fQlPeB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/937/1%2AIbD012o9Yh60jqMQqroZKg.png" alt="" width="800" height="587"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Pull Request showcasing Terraform Plan Results&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P_o9UCzq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/821/1%2AHP0-Ts_9L1FkciWB2I1rNA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P_o9UCzq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/821/1%2AHP0-Ts_9L1FkciWB2I1rNA.png" alt="" width="800" height="949"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Thorough Examination of Terraform Plan Details&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_fctJalO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ALiR_GIt-70pewVMYvntoXg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_fctJalO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ALiR_GIt-70pewVMYvntoXg.png" alt="" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Merge
&lt;/h4&gt;

&lt;p&gt;After a thorough review of the pull request and ensuring the Terraform plan results meet expectations, proceed to merge the pull request. This will trigger the Terraform apply process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jfm5nHSH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ARQVfpIZc-TSP7MBhz-VsIQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jfm5nHSH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ARQVfpIZc-TSP7MBhz-VsIQ.png" alt="" width="800" height="420"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Production Deployment&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5S-9brbM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/800/1%2A0wi-k-5NmQtG3KH68B-oVg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5S-9brbM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/800/1%2A0wi-k-5NmQtG3KH68B-oVg.png" alt="" width="800" height="672"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;In-Depth Exploration of the Terraform Workspace&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping it up
&lt;/h3&gt;

&lt;p&gt;In conclusion, we’ve explored the powerful capabilities of GitHub Actions in automating Terraform infrastructure deployments. If you’ve already followed my &lt;a href="https://thulasirajkomminar.com/efficient-continuous-deployment-with-github-environments-and-aws-codebuild-9086aef7d913"&gt;previous blog&lt;/a&gt; on code deployment using GitHub Actions, you can seamlessly combine these processes to achieve sequential infrastructure deployment and code deployment, streamlining your development workflow.&lt;/p&gt;




</description>
      <category>cicd</category>
      <category>terraform</category>
      <category>aws</category>
      <category>githubactions</category>
    </item>
    <item>
      <title>Efficient Continuous Deployment with GitHub Environments and AWS CodeBuild</title>
      <dc:creator>Thulasiraj Komminar</dc:creator>
      <pubDate>Mon, 30 Oct 2023 22:17:00 +0000</pubDate>
      <link>https://dev.to/aws-builders/efficient-continuous-deployment-with-github-environments-and-aws-codebuild-3e8e</link>
      <guid>https://dev.to/aws-builders/efficient-continuous-deployment-with-github-environments-and-aws-codebuild-3e8e</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Continuous Deployment (CD) is a methodology that leverages automation for releasing software updates efficiently. In a standard CD setup, code undergoes automatic building and testing phases prior to its deployment. With GitHub Actions, automating these software workflows becomes seamless. Configure your CD pipeline to initiate whenever there’s a GitHub event, such as a new code push or a pull request. For a comprehensive list of event triggers, &lt;a href="https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows"&gt;click here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Environments define common deployment targets such as &lt;code&gt;production&lt;/code&gt;, &lt;code&gt;staging&lt;/code&gt;, or &lt;code&gt;development&lt;/code&gt;. They can be set up with protection rules and associated secrets. When a workflow job references an environment, it only begins after satisfying all the environment’s protection rules. Moreover, a job can only access the secrets linked to an environment after all its deployment protection criteria are met.&lt;/p&gt;

&lt;p&gt;In this blog post, I’ll guide you through setting up a Continuous Deployment pipeline using GitHub Actions and environments, focusing on both &lt;code&gt;development&lt;/code&gt; and &lt;code&gt;production&lt;/code&gt; stages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initial setup
&lt;/h3&gt;

&lt;h4&gt;
  
  
  GitHub
&lt;/h4&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Environments:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;First, we’ll establish the &lt;code&gt;development&lt;/code&gt; and &lt;code&gt;production&lt;/code&gt; environments and implement deployment protection rules for added security.&lt;/p&gt;

&lt;p&gt;Navigate to the repository where you intend to set up the Continuous Deployment (CD). Click on &lt;em&gt;Settings&lt;/em&gt;, and then select &lt;em&gt;Environments&lt;/em&gt; from the sidebar. To add environments, simply click on the &lt;em&gt;New Environment&lt;/em&gt; button. As depicted in the image below, I have established two environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sLa3qUeG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ApZmHYcgL3qmxbjW2l2sJhA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sLa3qUeG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ApZmHYcgL3qmxbjW2l2sJhA.png" alt="" width="800" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After adding an environment, you’ll be prompted to configure its settings. Let’s dive into that. We’ll start by setting up a protection rule for the &lt;code&gt;production&lt;/code&gt; environment. As illustrated below, I’ve added a required reviewer to manually approve all deployments headed to production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vKAnblRQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AB1MYrImifqb-jvfO97QGfA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vKAnblRQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AB1MYrImifqb-jvfO97QGfA.png" alt="" width="800" height="586"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we’ll restrict deployments to this environment based on specific branch naming patterns. As demonstrated below, I selected the &lt;em&gt;Selected branches and tags rule&lt;/em&gt;. Click on &lt;em&gt;Add deployment branch or tag rule&lt;/em&gt;, and in the subsequent popup, select &lt;em&gt;Ref type&lt;/em&gt; as &lt;em&gt;branch&lt;/em&gt; and enter &lt;code&gt;main&lt;/code&gt; for the &lt;em&gt;Name pattern&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fXi37VBY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AG2GYqHrZu0EZT2vPsvg4Gg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fXi37VBY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AG2GYqHrZu0EZT2vPsvg4Gg.png" alt="" width="800" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To deploy to an AWS account, we require the AWS account ID and region. Therefore, I’ve added these as environment secrets, along with a variable to capture the environment name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aRcBzfPH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AbzbRVrLkuFO6dBICcTapRQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aRcBzfPH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AbzbRVrLkuFO6dBICcTapRQ.png" alt="" width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Likewise, I’ve configured deployment restrictions, environment secrets, and variables for the &lt;code&gt;development&lt;/code&gt; environment. However, I omitted the reviewer setup since this environment is solely for development deployments.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Actions:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Now, let’s proceed to create GitHub workflows so that deployments are automatically triggered whenever a commit is made to either the &lt;code&gt;develop&lt;/code&gt; or &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/komminarlabs/cd-with-github-actions/blob/main/.github/workflows/cd_production.yml"&gt;&lt;strong&gt;main&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CD - Production&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;codebuild&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Production&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo 'Deploying to ${{ vars.ENV }}'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check out code&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Configure AWS Credentials&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;role-to-assume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;arn:aws:iam::${{ secrets.AWS_ACCOUNTID }}:role/GitHubTriggerRole&lt;/span&gt;
          &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_REGION }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run CodeBuild&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/aws-codebuild-run-build@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;project-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CD-CodeBuild&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/komminarlabs/cd-with-github-actions/blob/main/.github/workflows/cd_development.yml"&gt;&lt;strong&gt;develop&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CD - Development&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;develop&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;codebuild&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Development&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo 'Deploying to ${{ vars.ENV }}'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check out code&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Configure AWS Credentials&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;role-to-assume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;arn:aws:iam::${{ secrets.AWS_ACCOUNTID }}:role/GitHubTriggerRole&lt;/span&gt;
          &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_REGION }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run CodeBuild&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/aws-codebuild-run-build@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;project-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CD-CodeBuild&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s delve into the deployment job’s steps. We’ve included four key actions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Echo:&lt;/strong&gt; This step simply prints the name of the environment being deployed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Check out code:&lt;/strong&gt; I’m utilizing a GitHub action to retrieve the code from the repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configure AWS Credentials:&lt;/strong&gt; In this step, I’ve set up an OIDC (OpenID Connect) configuration to enable role assumption, allowing me to make AWS service calls on behalf of the environment. I’ll provide a more detailed explanation of the OIDC setup in the next section, specifically focusing on AWS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run CodeBuild:&lt;/strong&gt; This final step initiates an AWS CodeBuild project and waits for its status, ensuring a smooth and coordinated deployment process.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Ensure that the environment name in the actions file corresponds with the GitHub repository’s environment name.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;Now, let’s explore what needs to be configured on the AWS side.&lt;/p&gt;

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

&lt;p&gt;We need to set up two roles: one for GitHub Actions to assume using OIDC, and another for the CodeBuild project to assume.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OIDC:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To begin, log in to the AWS console and navigate to the IAM service. In the sidebar, select &lt;em&gt;Identity providers&lt;/em&gt; and click on &lt;em&gt;Add Provider&lt;/em&gt;. In the &lt;em&gt;Configure provider&lt;/em&gt; window, choose the &lt;em&gt;OpenID Connect&lt;/em&gt; option.&lt;/p&gt;

&lt;p&gt;Here are the specific details you’ll need to fill in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For the Provider URL, use &lt;code&gt;https://token.actions.githubusercontent.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;For the Audience, enter &lt;code&gt;sts.amazonaws.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Finally, click &lt;em&gt;Add Provider&lt;/em&gt; to complete the setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More details on this can be found &lt;a href="https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create IAM Roles:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. GitHub role:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, within the IAM services, select &lt;em&gt;Create role&lt;/em&gt;. Opt for the &lt;em&gt;Custom trust policy&lt;/em&gt; as the trusted entity type.&lt;/p&gt;

&lt;p&gt;Here’s the trust policy text that you should use in the custom trust policy text box:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace the GitHub &lt;code&gt;username/repository&lt;/code&gt; with your own.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"Federated"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:iam::${account-id}:oidc-provider/token.actions.githubusercontent.com"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sts:AssumeRoleWithWebIdentity"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"StringEquals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"token.actions.githubusercontent.com:aud"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sts.amazonaws.com"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"StringLike"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"token.actions.githubusercontent.com:sub"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"repo:komminarlabs/cd-with-github-actions:*"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Name the role as &lt;code&gt;GitHubTriggerRole&lt;/code&gt;. After creating the role, attach the following policy as an inline policy to grant access for writing logs to CloudWatch and the necessary permissions to trigger a CodeBuild project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"logs:PutLogEvents"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"logs:GetLogEvents"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"logs:CreateLogStream"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"logs:CreateLogGroup"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:logs:eu-central-1:${account-id}:*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"codebuild:UpdateReport"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"codebuild:StartBuild"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"codebuild:CreateReportGroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"codebuild:CreateReport"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"codebuild:BatchPutTestCases"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"codebuild:BatchPutCodeCoverages"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"codebuild:BatchGetBuilds"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. CodeBuild Role:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, let’s create a second role for CodeBuild to assume. When you click the &lt;em&gt;Create role&lt;/em&gt; button, select &lt;em&gt;CodeBuild&lt;/em&gt; as the AWS Service. Attach the existing managed policy &lt;code&gt;AWSCodeBuildAdminAccess&lt;/code&gt; to this role.&lt;/p&gt;

&lt;h4&gt;
  
  
  CodeBuild
&lt;/h4&gt;

&lt;p&gt;Now, head over to the CodeBuild service and select &lt;em&gt;Create build project&lt;/em&gt;. Specify the project name as &lt;em&gt;CD-CodeBuild&lt;/em&gt;. In the Source section, choose &lt;em&gt;GitHub&lt;/em&gt; from the dropdown and include the Repository URL: &lt;a href="https://github.com/komminarlabs/cd-with-github-actions"&gt;https://github.com/komminarlabs/cd-with-github-actions&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: You have the option to authenticate with GitHub using either OAuth or a personal token.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Apply the following Environment settings, and select the role you previously created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zWra4HDX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AhnUt8DnZxPvTX1XTnNdZgg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zWra4HDX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AhnUt8DnZxPvTX1XTnNdZgg.png" alt="" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EyEcxb00--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AGW8zNEh22tjg7jy3zQCnzw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EyEcxb00--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AGW8zNEh22tjg7jy3zQCnzw.png" alt="" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select &lt;em&gt;Insert build commands&lt;/em&gt; under &lt;em&gt;Buildspec&lt;/em&gt;, then paste the following content. Finally, create the CodeBuild project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.2&lt;/span&gt;

&lt;span class="na"&gt;phases&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runtime-versions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3.11&lt;/span&gt;

  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "This is a test"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Development
&lt;/h4&gt;

&lt;p&gt;Alright, now that we’ve configured everything on both the GitHub and AWS sides, it’s time to put our setup to the test. To do this, I used a &lt;code&gt;dummy_file.txt&lt;/code&gt; in the GitHub repository for testing purposes.&lt;/p&gt;

&lt;p&gt;After pushing a change directly to the &lt;code&gt;develop&lt;/code&gt; branch, it promptly initiated a deployment to the &lt;code&gt;development&lt;/code&gt; environment. The deployment was successful, and you can view the corresponding CodeBuild logs within the Actions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RrcIa4vc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AfhSaPB7dTBt8_pSwF4Yd3A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RrcIa4vc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AfhSaPB7dTBt8_pSwF4Yd3A.png" alt="" width="800" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AtR8JUhX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AoztCjoPChGuWX1t05-1A1w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AtR8JUhX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AoztCjoPChGuWX1t05-1A1w.png" alt="" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ubkd7Exv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AQmVbTl0NMfO0m_OrnpELPw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ubkd7Exv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AQmVbTl0NMfO0m_OrnpELPw.png" alt="" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Production
&lt;/h4&gt;

&lt;p&gt;With the successful deployment to the &lt;code&gt;development&lt;/code&gt; environment, let’s now create a pull request to the &lt;code&gt;main&lt;/code&gt; branch to trigger the &lt;code&gt;production&lt;/code&gt; deployment.&lt;/p&gt;

&lt;p&gt;As depicted below, the pull request to main displays the status of the deployment to &lt;code&gt;development&lt;/code&gt;. You can enforce this deployment check as mandatory in the branch protection rules for added reliability.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VO-M3uyz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AexggeakS6_5HfvjzSEEkig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VO-M3uyz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AexggeakS6_5HfvjzSEEkig.png" alt="" width="800" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, proceed to merge this pull request. The deployment to the &lt;code&gt;production&lt;/code&gt; environment will pause and await manual approval, as we’ve included reviewers as a protection rule in the &lt;code&gt;production&lt;/code&gt; environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rKDSRqbK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Ako4jvQE4lRdRDWZF0m8nvA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rKDSRqbK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Ako4jvQE4lRdRDWZF0m8nvA.png" alt="" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alright, after a thorough manual review of the changes 😊, let’s proceed with approving this deployment. To do so, click on &lt;em&gt;Review deployments&lt;/em&gt;, select the &lt;code&gt;production&lt;/code&gt; environment, and then click on &lt;em&gt;Approve and deploy&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LfInw38o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AM0qdtpf41SyYt7PfKtdhaw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LfInw38o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AM0qdtpf41SyYt7PfKtdhaw.png" alt="" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the approval in place, the &lt;code&gt;production&lt;/code&gt; deployment process is now initiated.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fhIn9ax4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AfpSOQBI1prRfrPzuugSudQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fhIn9ax4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AfpSOQBI1prRfrPzuugSudQ.png" alt="" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping it up
&lt;/h3&gt;

&lt;p&gt;I hope this blog has provided you with a clear understanding of how to leverage GitHub environments to enhance your continuous deployment process.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>githubactions</category>
      <category>continuousdeployment</category>
      <category>codebuild</category>
    </item>
    <item>
      <title>What is HashiCorp Terraform?</title>
      <dc:creator>Thulasiraj Komminar</dc:creator>
      <pubDate>Fri, 22 Sep 2023 14:29:07 +0000</pubDate>
      <link>https://dev.to/thulasirajkomminar/what-is-hashicorp-terraform-3col</link>
      <guid>https://dev.to/thulasirajkomminar/what-is-hashicorp-terraform-3col</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YN516hUj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AL2b3v0kFfopd-Tfk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YN516hUj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AL2b3v0kFfopd-Tfk.png" alt="" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In this blog I will explain what is Terraform and some of its common terms. I will also list some good to follow standards when you start using Terraform.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is it?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Terraform is an infrastructure as code tool that lets you define both cloud and on-premise resources in human-readable configuration files.&lt;/li&gt;
&lt;li&gt;It can manage both low-level(Networking, Storage) &amp;amp; high-level components(DNS, SaaS).&lt;/li&gt;
&lt;li&gt;It can be used to manage single application and also an entire datacenter.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What it isn’t?
&lt;/h3&gt;

&lt;p&gt;It is not a configuration management tool that focuses on single application configuration but Terraform focuses on higher-level abstraction like managing the entire environment&lt;/p&gt;

&lt;h3&gt;
  
  
  Terraform Editions
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Open Source&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;A free to download tool that you interact with CLI.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Terraform Cloud&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;SaaS application that runs in a secure remote environment and stores states and secrets.&lt;/li&gt;
&lt;li&gt;Connects to VCS and new commits triggers Terraform automatically.&lt;/li&gt;
&lt;li&gt;It has Rich UI and RBAC controls.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Terraform Enterprise&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Self-hosted distribution of Terraform Cloud. It offers enterprises a private instance of the Terraform Cloud application, with no resource limits and with additional enterprise-grade architectural features like audit logging and SAML single sign-on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Terraform Jargons
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Workspace&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;A workspace contains everything that Terraform needs to manage a given collection of infrastructure.&lt;/li&gt;
&lt;li&gt;It links to VCS and has Variables, Credentials, Secrets, State versions, and Run History.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Backend&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;A backend defines where Terraform stores its state data files.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;cloud&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;organization&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"sampleorg"&lt;/span&gt;

    &lt;span class="nx"&gt;workspaces&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;"dev-workspace"&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;h4&gt;
  
  
  &lt;strong&gt;Provider&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Provides abstraction to APIs that connect to the infrastructure hosts.&lt;/li&gt;
&lt;li&gt;Without providers, Terraform can’t manage any kind of infrastructure.&lt;/li&gt;
&lt;li&gt;Every provider makes a list of resources and data types available for use in the Terraform code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Registry&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The Terraform Registry is an interactive resource for discovering a wide selection of integrations (providers), configuration packages (modules), and security rules (policies) for use with Terraform.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;HCL&lt;/strong&gt; (HashiCorp Configuration Language)
&lt;/h4&gt;

&lt;p&gt;HCL is a declarative and domain-specific language.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;State&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Terraform is a stateful application, meaning it keeps track of everything it builds in the infrastructure.&lt;/li&gt;
&lt;li&gt;State is used by Terraform to map real-world resources to your configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How Terraform works?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Terraform creates and manages resources on cloud platforms and other services through their APIs.&lt;/li&gt;
&lt;li&gt;Providers enable Terraform to work with virtually any platform or service with an accessible API.&lt;/li&gt;
&lt;li&gt;The core Terraform workflow consists of three stages:&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Write:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Defining resources&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Plan:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;An execution plan that describes the infra terraform will create/update/destroy based on existing infra and your configurations.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Apply:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Performing the operations in the correct order by respecting resource dependencies. Can be automatic or manual.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuration Language
&lt;/h3&gt;

&lt;p&gt;Terraform supports HCL, JSON, CRDS and CDK. CDK allows you to use familiar programming languages to define and provision infrastructure. It also lets you leverage the power of your existing toolchain for testing, dependency management, etc. In this blog we will focus on HCL and how to configure Providers, Resources and Modules.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6i40l0BY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2Ai1ORp-D4rffLNyQY" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6i40l0BY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2Ai1ORp-D4rffLNyQY" alt="" width="800" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  HCL
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Provider&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Terraform Cloud and Terraform Enterprise install providers as part of every run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Provider configuration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Provider configurations belong in the root module of a Terraform configuration. Child modules receive their provider configurations from the root module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;alias&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us_east_1"&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Provider Requirements&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each Terraform module must declare which providers it requires, so that Terraform can install and use them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;mycloud&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mycorp/mycloud"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.0"&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;h4&gt;
  
  
  &lt;strong&gt;Variables, Outputs, and Locals&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In comparison with traditional programming languages,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input variables are like function arguments.&lt;/li&gt;
&lt;li&gt;Output values are like function return values.&lt;/li&gt;
&lt;li&gt;Local values are like a function’s temporary local variables.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"image_id"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"instance_ip_addr"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;private_ip&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;common_tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Stack&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt;
    &lt;span class="nx"&gt;Environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&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;h4&gt;
  
  
  Resource
&lt;/h4&gt;

&lt;p&gt;Each resource block describes one or more infrastructure objects, such as virtual networks, compute instances, or higher-level components such as DNS records.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_athena_workgroup"&lt;/span&gt; &lt;span class="s2"&gt;"default"&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;"default"&lt;/span&gt;
  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;locals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;common_tags&lt;/span&gt;

  &lt;span class="nx"&gt;configuration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;enforce_workgroup_configuration&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="nx"&gt;publish_cloudwatch_metrics_enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="nx"&gt;result_configuration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;output_location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"s3://some-bucket/path"&lt;/span&gt;

      &lt;span class="nx"&gt;encryption_configuration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;encryption_option&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SSE_S3"&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;h4&gt;
  
  
  &lt;strong&gt;Data Sources&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Data sources allow Terraform to use information defined outside of Terraform.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_vpc"&lt;/span&gt; &lt;span class="s2"&gt;"default"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vpc-0aexzk638sp5h9u7v"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Modules&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Containers for multiple resources that are used together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Root Module&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every Terraform configuration has at least one module, known as its root module, which consists of the resources defined in the .tf files in the main working directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Child Modules&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A module that has been called by another module is often referred to as a child module.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Published Modules&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In addition to modules from the local filesystem, Terraform can load modules from a public or private registry.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"example_glue_job"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"github.com/komminar/terraform-aws-glue-job?ref=v0.1.0"&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;"example-glue-job"&lt;/span&gt;
  &lt;span class="nx"&gt;max_retries&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="nx"&gt;number_of_workers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="nx"&gt;schedule&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"cron(0 12 * * ? *)"&lt;/span&gt;
  &lt;span class="nx"&gt;script_location&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"S3://example-bucket/location/script.py"&lt;/span&gt;
  &lt;span class="nx"&gt;trigger_type&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SCHEDULED"&lt;/span&gt;
  &lt;span class="nx"&gt;worker_type&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Standard"&lt;/span&gt;

  &lt;span class="nx"&gt;default_arguments&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"--VAR1"&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"some value"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"development"&lt;/span&gt;
    &lt;span class="nx"&gt;Stack&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"glue"&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 can find some of my AWS Terraform modules &lt;a href="https://github.com/thulasirajkomminar?tab=repositories&amp;amp;q=terraform-aws&amp;amp;type=&amp;amp;language=&amp;amp;sort="&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Standards
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;em&gt;count&lt;/em&gt; only for enabling/disabling resource creation and use &lt;em&gt;for_each&lt;/em&gt; for loops.&lt;/li&gt;
&lt;li&gt;Variables are ordered A-Z, but tags always comes at last.&lt;/li&gt;
&lt;li&gt;Multi-line list or map should be in new line.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_sagemaker_domain"&lt;/span&gt; &lt;span class="s2"&gt;"default"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;domain_name&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;app_network_access_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;app_network_access_type&lt;/span&gt;
  &lt;span class="nx"&gt;auth_mode&lt;/span&gt;               &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"IAM"&lt;/span&gt;
  &lt;span class="nx"&gt;subnet_ids&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet_ids&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vpc_id&lt;/span&gt;
  &lt;span class="nx"&gt;tags&lt;/span&gt;                    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;

  &lt;span class="nx"&gt;default_user_settings&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;execution_role&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role_arn&lt;/span&gt; &lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role_arn&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;aws_iam_role&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;default&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;
    &lt;span class="nx"&gt;security_groups&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;security_groups&lt;/span&gt;

    &lt;span class="nx"&gt;jupyter_server_app_settings&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;lifecycle_config_arns&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_sagemaker_studio_lifecycle_config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jupyter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

      &lt;span class="nx"&gt;default_resource_spec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;instance_type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"system"&lt;/span&gt;
        &lt;span class="nx"&gt;lifecycle_config_arn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_sagemaker_studio_lifecycle_config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jupyter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;kernel_gateway_app_settings&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;lifecycle_config_arns&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_sagemaker_studio_lifecycle_config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

      &lt;span class="nx"&gt;default_resource_spec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;instance_type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"system"&lt;/span&gt;
        &lt;span class="nx"&gt;lifecycle_config_arn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_sagemaker_studio_lifecycle_config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&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;ul&gt;
&lt;li&gt;There are some linters already available for you to use&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/terraform-linters/tflint"&gt;https://github.com/terraform-linters/tflint&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/terraform-linters/tflint-ruleset-terraform"&gt;https://github.com/terraform-linters/tflint-ruleset-terraform&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/terraform-linters/tflint-ruleset-aws"&gt;https://github.com/terraform-linters/tflint-ruleset-aws&lt;/a&gt;&lt;/p&gt;

</description>
      <category>hashicorp</category>
      <category>howto</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
  </channel>
</rss>
