From 0dd4f9467917cd2b6bcdd690d2ee310cd8a9824b Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Tue, 9 Oct 2018 03:43:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0ansible-inventory=E8=84=9A?= =?UTF-8?q?=E6=9C=AC=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/climc/ansible/README.md | 33 +++++++++ cmd/climc/shell/ansible.go | 129 ++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 cmd/climc/ansible/README.md create mode 100644 cmd/climc/shell/ansible.go diff --git a/cmd/climc/ansible/README.md b/cmd/climc/ansible/README.md new file mode 100644 index 0000000000..ca913bde3b --- /dev/null +++ b/cmd/climc/ansible/README.md @@ -0,0 +1,33 @@ +Howto +===== + +Make climc as an ansible inventory source. + +1. Edit /etc/ansible/hosts + +``` +#!/bin/bash + +export OS_USERNAME=sysadmin +export OS_PASSWORD= +export OS_PROJECT_NAME=system +export OS_DOMAIN_NAME=Default +export OS_AUTH_URL=http://10.168.200.246:5000/v3 +export OS_REGION_NAME=YunionHQ + +/opt/yunion/bin/climc ansible-hosts --port 22 --user yunion --private-key $HOME/priv-key --user-become root $@ +``` + + +2. Make /etc/ansible/hosts executable + +```sh +chmod +x /etc/ansible/hosts +``` + +3. Try + +```sh +ansible-inventory --list +ansible-inventory --host +``` diff --git a/cmd/climc/shell/ansible.go b/cmd/climc/shell/ansible.go new file mode 100644 index 0000000000..38ba093498 --- /dev/null +++ b/cmd/climc/shell/ansible.go @@ -0,0 +1,129 @@ +package shell + +import ( + "fmt" + "strings" + + "yunion.io/x/jsonutils" + + "yunion.io/x/onecloud/pkg/mcclient" + "yunion.io/x/onecloud/pkg/mcclient/modules" +) + +type AnsibleHostsOptions struct { + List bool `help:"List all ansible inventory"` + Host string `help:"List of a host"` + PrivateKey string `help:"path to private key to use for ansible"` + Port int `help:"optional port, if port is not 22"` + User string `help:"username to try"` + UserBecome string `help:"username to sudo"` +} + +func serverGetNameIP(srv jsonutils.JSONObject) (string, string, error) { + host, _ := srv.GetString("name") + if len(host) == 0 { + return "", "", fmt.Errorf("No name for server") + } + ips, _ := srv.GetString("ips") + if len(ips) == 0 { + return "", "", fmt.Errorf("no ips for server %s", host) + } + ipList := strings.Split(ips, ",") + if len(ipList) == 0 { + return "", "", fmt.Errorf("no valid ips for server %s", host) + } + return host, ipList[0], nil +} + + +func doList(s *mcclient.ClientSession, args *AnsibleHostsOptions) error { + hostVars := jsonutils.NewDict() + hosts := jsonutils.NewArray() + + limit := 2048 + total := 1 + for hosts.Size() < total { + params := jsonutils.NewDict() + params.Add(jsonutils.NewInt(int64(limit)), "limit") + params.Add(jsonutils.NewInt(int64(hosts.Size())), "offset") + params.Add(jsonutils.JSONTrue, "details") + retList, err := modules.Servers.List(s, params) + if err != nil { + return err + } + if len(retList.Data) > 0 { + for i := 0; i < len(retList.Data); i += 1 { + host, ip, err := serverGetNameIP(retList.Data[i]) + if err == nil { + hosts.Add(jsonutils.NewString(host)) + hostVars.Add(jsonutils.NewString(ip), host, "ansible_host") + if args.Port > 0 { + hostVars.Add(jsonutils.NewInt(int64(args.Port)), host, "ansible_port") + } + if len(args.PrivateKey) > 0 { + hostVars.Add(jsonutils.NewString(args.PrivateKey), host, "ansible_ssh_private_key_file") + } + if len(args.User) > 0 { + hostVars.Add(jsonutils.NewString(args.User), host, "ansible_user") + } + if len(args.UserBecome) > 0 { + hostVars.Add(jsonutils.NewString(args.UserBecome), host, "ansible_become_user") + } + } + } + } + total = retList.Total + } + + output := jsonutils.NewDict() + output.Add(hostVars, "_meta", "hostvars") + children := jsonutils.NewArray(jsonutils.NewString("ungrouped")) + output.Add(children, "all", "children") + output.Add(hosts, "ungrouped", "hosts") + + fmt.Printf("%s", output.PrettyString()) + + return nil +} + + +func doHost(s *mcclient.ClientSession, host string, args *AnsibleHostsOptions) error { + srv, err := modules.Servers.Get(s, host, nil) + if err != nil { + return err + } + _, ipstr, err := serverGetNameIP(srv) + if err != nil { + return err + } + hostVar := jsonutils.NewDict() + hostVar.Add(jsonutils.NewString(ipstr), "ansible_host") + if args.Port > 0 { + hostVar.Add(jsonutils.NewInt(int64(args.Port)), "ansible_port") + } + if len(args.PrivateKey) > 0 { + hostVar.Add(jsonutils.NewString(args.PrivateKey), "ansible_ssh_private_key_file") + } + if len(args.User) > 0 { + hostVar.Add(jsonutils.NewString(args.User), "ansible_user") + } + if len(args.UserBecome) > 0 { + hostVar.Add(jsonutils.NewString(args.UserBecome), "ansible_become_user") + } + + fmt.Printf("%s", hostVar.PrettyString()) + + return nil +} + +func init() { + R(&AnsibleHostsOptions{}, "ansible-hosts", "List ansible inventory", func(s *mcclient.ClientSession, args *AnsibleHostsOptions) error { + if len(args.Host) > 0 { + return doHost(s, args.Host, args) + } else if args.List { + return doList(s, args) + } else { + return fmt.Errorf("Invalid arguments, either --list or --host must be specified") + } + }) +}