| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package models
- import (
- "context"
- "strings"
- "yunion.io/x/jsonutils"
- "yunion.io/x/pkg/util/regutils"
- "yunion.io/x/onecloud/pkg/cloudcommon/validators"
- "yunion.io/x/onecloud/pkg/httperrors"
- mcclient "yunion.io/x/onecloud/pkg/mcclient"
- mcclient_auth "yunion.io/x/onecloud/pkg/mcclient/auth"
- mcclient_models "yunion.io/x/onecloud/pkg/mcclient/models"
- "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
- "yunion.io/x/onecloud/pkg/util/ansible"
- )
- type ValidatorAnsiblePlaybook struct {
- validators.Validator
- Playbook *ansible.Playbook
- userCred mcclient.TokenCredential
- }
- func NewAnsiblePlaybookValidator(key string, userCred mcclient.TokenCredential) *ValidatorAnsiblePlaybook {
- v := &ValidatorAnsiblePlaybook{
- Validator: validators.Validator{Key: key},
- userCred: userCred,
- }
- v.SetParent(v)
- return v
- }
- func (v *ValidatorAnsiblePlaybook) Validate(ctx context.Context, data *jsonutils.JSONDict) error {
- pb := ansible.NewPlaybook()
- err := data.Unmarshal(pb, "playbook")
- if err != nil {
- return httperrors.NewBadRequestError("unmarshaling json: %v", err)
- }
- hosts := pb.Inventory.Hosts
- for i := range hosts {
- name := strings.TrimSpace(hosts[i].Name)
- if len(name) == 0 {
- return httperrors.NewBadRequestError("empty host name")
- }
- defaultUsername := ansible.PUBLIC_CLOUD_ANSIBLE_USER
- switch {
- case regutils.MatchIP4Addr(name):
- case strings.HasPrefix(name, "host:"):
- var err error
- name = strings.TrimSpace(name[len("host:"):])
- name, err = v.getHostAccessIp(name)
- if err != nil {
- return err
- }
- defaultUsername = "root"
- case strings.HasPrefix(name, "server:"):
- name = name[len("server:"):]
- fallthrough
- default:
- var err error
- name = strings.TrimSpace(name)
- name, err = v.getServerIp(name)
- if err != nil {
- return err
- }
- }
- hosts[i].Name = name
- if username, _ := hosts[i].GetVar("ansible_user"); username == "" {
- if defaultUsername != "" {
- hosts[i].SetVar("ansible_user", defaultUsername)
- }
- }
- }
- // add LF for privateKey
- if len(pb.PrivateKey) > 0 && pb.PrivateKey[len(pb.PrivateKey)-1] != 10 {
- pb.PrivateKey = append(pb.PrivateKey, 10)
- }
- pbJson := jsonutils.Marshal(pb)
- if serialized := pbJson.String(); len(serialized) > PlaybookMaxBytes {
- return httperrors.NewBadRequestError("playbook too big, got %d bytes, exceeding %d",
- len(serialized), PlaybookMaxBytes)
- }
- v.Playbook = pb
- data.Set("playbook", pbJson)
- return nil
- }
- func (v *ValidatorAnsiblePlaybook) getHostAccessIp(name string) (string, error) {
- sess := mcclient_auth.GetSession(context.Background(), v.userCred, "")
- hostJson, err := compute.Hosts.Get(sess, name, nil)
- if err != nil {
- return "", httperrors.NewBadRequestError("cannot find host %s", name)
- }
- host := &mcclient_models.Host{}
- if err := hostJson.Unmarshal(host); err != nil {
- return "", httperrors.NewBadRequestError("unmarshal host %s: %v", name, err)
- }
- if host.AccessIp == "" {
- return "", httperrors.NewBadRequestError("host %s has no access ip", name)
- }
- return host.AccessIp, nil
- }
- func (v *ValidatorAnsiblePlaybook) getServerIp(name string) (string, error) {
- sess := mcclient_auth.GetSession(context.Background(), v.userCred, "")
- serverJson, err := compute.Servers.Get(sess, name, nil)
- if err != nil {
- return "", httperrors.NewBadRequestError("find server %s: %v", name, err)
- }
- server := &mcclient_models.Server{}
- if err := serverJson.Unmarshal(server); err != nil {
- return "", httperrors.NewBadRequestError("unmarshal server %s: %v", name, err)
- }
- serverNetworks, err := mcclient_models.ParseServerNetworkDetailedString(server.Networks)
- if err != nil {
- return "", httperrors.NewConflictError("parse networks of %s: %v", name, err)
- }
- ips := serverNetworks.GetPrivateIPs()
- if len(ips) == 0 {
- return "", httperrors.NewBadRequestError("server %s has no private ips", name)
- }
- name = ips[0].String()
- return name, nil
- }
|