简体   繁体   English

可以让 Ansible 与 Pulumi 合作吗?

[英]Is getting Ansible to work with Pulumi possible?

I wish to create several droplets (DigitalOcean) in a loop and then run Ansible afterwards on the droplets to setup the required software and security measures.我希望在循环中创建多个 droplet (DigitalOcean),然后在 droplet 上运行 Ansible 以设置所需的软件和安全措施。 Is this possible like terraform?这可能像 terraform 吗? If so, how would this look in javascript/typescript code?如果是这样,这在 javascript/typescript 代码中看起来如何?

There isn't anything in google that has any examples to create this or any mention of Pulumi with Ansible.谷歌中没有任何内容可以创建此示例或使用 Ansible 提及 Pulumi。

Yes, this is possible.是的,这是可能的。

You can do it one of 2 ways:您可以通过以下两种方式之一进行操作:

You can specify your ansible run inside the userdata of the DigitalOcean droplet.您可以在里面指定ansible运行用户数据的DigitalOcean液滴。 This works across all language SDKs.这适用于所有语言 SDK。

Alternatively, if you want to have similar functionality to Terraform's remote-exec provisioner, you can use Pulumi's dynamic providers to create a provisioner.或者,如果您想拥有与 Terraform 的 remote-exec 配置器类似的功能,您可以使用 Pulumi 的动态提供器来创建一个配置器。

Dynamic Providers are currently available in the TypeScript and Python SDKs.动态提供程序目前在 TypeScript 和 Python SDK 中可用。 You can find python example here and a TypeScript example here你可以找到蟒蛇例如这里和打字稿例子在这里

Here is an example of how you can use it to deploy wordpress via a playbook using local.Command provider and letting ansible provision on a remote host这是一个示例,说明如何使用它通过使用 local.Command 提供程序的剧本部署 wordpress,并让 ansible 在远程主机上进行配置

import * as command from '@pulumi/command'
import * as pulumi from '@pulumi/pulumi'
import * as fs from 'fs'
import {URL} from 'url'
import YAML from 'yaml'

const __dirname = new URL('.', import.meta.url).pathname
nunjucks.configure(`${__dirname}/templates`)

export interface WordPressArgs {
  fqdn: pulumi.Input<string>
  ip: pulumi.Input<string>
  sshPort: pulumi.Input<number>
  sshPrivateKey: pulumi.Input<string>
  sshUser: pulumi.Input<string>
  domainUser: pulumi.Input<string>
  domainUserHomeDir?: pulumi.Input<string>
  domainUserDocumentRootDir?: pulumi.Input<string>
  nginxUser?: pulumi.Input<string>
  wordpressLanguage?: pulumi.Input<string>
  wordpressDbName: pulumi.Input<string>
  wordpressDbUser: pulumi.Input<string>
  wordpressDbPassword: pulumi.Input<string>
  wordpressDbHost?: pulumi.Input<string>
  wordpressTitle?: pulumi.Input<string>
  wordpressAdminUser?: pulumi.Input<string>
  wordpressAdminPassword: pulumi.Input<string>
  wordpressAdminEmail?: pulumi.Input<string>
  deploymentEnvironment?: pulumi.Input<'production' | 'staging' | 'testing'>
}

export class WordPress extends pulumi.ComponentResource {
  private readonly wordPressInstallCommand: pulumi.Output<string>

  constructor(
    name: string,
    args: WordPressArgs,
    opts?: pulumi.ComponentResourceOptions
  ) {
    super('system:virtualmin:wordpress', name, {}, opts)

    const cmd = pulumi
      .all(
        [
          args.fqdn,
          args.ip,
          args.sshPort,
          args.sshUser,
          args.sshPrivateKey,
          args.domainUser,
          args.nginxUser,
          args.wordpressLanguage,
          args.wordpressDbHost,
          args.wordpressDbName,
          args.wordpressDbUser,
          args.wordpressDbPassword,
          args.wordpressTitle,
          args.wordpressAdminUser,
          args.wordpressAdminPassword,
          args.wordpressAdminEmail,
          args.deploymentEnvironment]
      )
      .apply((
          [
            fqdn,
            ip,
            sshPort,
            sshUser,
            sshPrivateKey,
            domainUser,
            nginxUser,
            wordpressLanguage,
            wordpressDbHost,
            wordpressDbName,
            wordpressDbUser,
            wordpressDbPassword,
            wordpressTitle,
            wordpressAdminUser,
            wordpressAdminPassword,
            wordpressAdminEmail,
            deploymentEnvironment]
        ) => {

          fs.writeFileSync(
            `/tmp/ansible.pem`,
            sshPrivateKey.toString(),
            {mode: 0o600}
          )

          fs.writeFileSync(
            '/tmp/inventory',
            YAML.stringify(
              {
                all: {
                  hosts: {
                    remote: {
                      ansible_host: ip,
                      ansible_port: sshPort,
                      ansible_user: sshUser,
                      ansible_private_key_file: '/tmp/ansible.pem',
                      ansible_host_key_checking: false
                    }
                  }
                }
              }),
            {mode: 0o600}
          )

          const playbookVars = pulumi.interpolate`${JSON.stringify({
            fqdn,
            deployment_environment: deploymentEnvironment || 'staging',
            domain_user: domainUser,
            nginx_user: nginxUser || 'www-data',
            wordpress_language: wordpressLanguage || 'en_US',
            wordpress_db_host: wordpressDbHost || 'localhost:3306',
            wordpress_db_name: wordpressDbName,
            wordpress_db_user: wordpressDbUser,
            wordpress_db_password: wordpressDbPassword,
            wordpress_title: wordpressTitle || 'Just a WordPress site',
            wordpress_admin_user: wordpressAdminUser || 'admin',
            wordpress_admin_password: wordpressAdminPassword,
            wordpress_admin_email: wordpressAdminEmail,
            ssl_cert_dir: '/etc/ssl/certs',
            ssl_key_dir: '/etc/ssl/private'
          })}`
          return {create: pulumi.interpolate`ANSIBLE_STDOUT_CALLBACK=json ansible-playbook -i /tmp/inventory ${__dirname}/playbooks/install-wordpress.yaml -e '${playbookVars}'`}
        }
      )


    this.wordPressInstallCommand = cmd.create
    const wordPressInstallation = new command.local.Command(
      'wordpress-installation',
      {
        create: this.wordPressInstallCommand,
      },
      {parent: this}
    )

    this.registerOutputs()
  }
}

@Dreamystify yes, this is possible in terraform. @Dreamystify 是的,这在 terraform 中是可能的。 In short, with help of terraform var file, provider remote and local execution you can achieve this.简而言之,借助 terraform var 文件、提供程序远程和本地执行,您可以实现这一点。 I tried this for aws instances, where I was having requirement to create multiple similar instances and then to run ansible command on all created instances.我为 aws 实例尝试了这个,我需要创建多个类似的实例,然后在所有创建的实例上运行 ansible 命令。 You can find complete details in below medium article.您可以在以下中等文章中找到完整的详细信息。

https://medium.com/@hegdetapan2609/how-to-install-packages-on-multiple-similar-instances-at-same-time-using-terraform-182582af5260 https://medium.com/@hegdetapan2609/how-to-install-packages-on-multiple-similar-instances-at-same-time-using-terraform-182582af5260

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM