mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-10-25 10:16:12 +08:00
feat/ansible_pb: Add support for requirements
You can declare the source info of the referenced role in requirements.
This commit is contained in:
@@ -39,12 +39,13 @@ import (
|
||||
type SAnsiblePlaybookV2 struct {
|
||||
db.SVirtualResourceBase
|
||||
|
||||
Playbook string `length:"text" nullable:"false" create:"required" get:"user"`
|
||||
Inventory string `length:"text" nullable:"false" create:"required" get:"user"`
|
||||
Files string `length:"text" nullable:"false" create:"optional" get:"user"`
|
||||
Output string `length:"medium" get:"user"`
|
||||
StartTime time.Time `list:"user"`
|
||||
EndTime time.Time `list:"user"`
|
||||
Playbook string `length:"text" nullable:"false" create:"required" get:"user"`
|
||||
Inventory string `length:"text" nullable:"false" create:"required" get:"user"`
|
||||
Requirements string `length:"test" nullable:"false" create:"required" get:"user"`
|
||||
Files string `length:"text" nullable:"false" create:"optional" get:"user"`
|
||||
Output string `length:"medium" get:"user"`
|
||||
StartTime time.Time `list:"user"`
|
||||
EndTime time.Time `list:"user"`
|
||||
|
||||
CreatorMark string `length:"32" nullable:"false" create:"optional" get:"user"`
|
||||
}
|
||||
@@ -196,6 +197,7 @@ func (apb *SAnsiblePlaybookV2) runPlaybook(ctx context.Context, userCred mcclien
|
||||
Inventory(apb.Inventory).
|
||||
Playbook(apb.Playbook).
|
||||
PrivateKey(privateKey).
|
||||
Requirements(apb.Requirements).
|
||||
Files(files).
|
||||
OutputWriter(&ansiblePlaybookOutputWriter{apb})
|
||||
man.sessions.Add(apb.Id, sess)
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
// 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 ansiblev2
|
||||
|
||||
import "gopkg.in/yaml.v2"
|
||||
|
||||
type RoleSource struct {
|
||||
Name string
|
||||
Src string
|
||||
Version string
|
||||
}
|
||||
|
||||
func (rs *RoleSource) MarshalYAML() (interface{}, error) {
|
||||
r := map[string]string{
|
||||
"src": rs.Src,
|
||||
}
|
||||
if len(rs.Name) > 0 {
|
||||
r["name"] = rs.Name
|
||||
}
|
||||
if len(rs.Version) > 0 {
|
||||
r["version"] = rs.Version
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
type Requirements struct {
|
||||
RoleSources []RoleSource
|
||||
}
|
||||
|
||||
func NewRequirements(rss ...RoleSource) *Requirements {
|
||||
return &Requirements{
|
||||
RoleSources: rss,
|
||||
}
|
||||
}
|
||||
|
||||
func (rm *Requirements) AddRoleSource(rss ...RoleSource) {
|
||||
rm.RoleSources = append(rm.RoleSources, rss...)
|
||||
}
|
||||
|
||||
func (rm *Requirements) MarshalYAML() (interface{}, error) {
|
||||
var err error
|
||||
r := make([]interface{}, len(rm.RoleSources))
|
||||
for i := range rm.RoleSources {
|
||||
r[i], err = rm.RoleSources[i].MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (rm *Requirements) String() string {
|
||||
r, err := yaml.Marshal(rm)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(r)
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// 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 ansiblev2
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestRequirementsString(t *testing.T) {
|
||||
rss := []RoleSource{
|
||||
{
|
||||
Src: "zaiste.nginx",
|
||||
},
|
||||
{
|
||||
Src: "geerlingguy.gitlab",
|
||||
Version: "1.1.0",
|
||||
},
|
||||
{
|
||||
Name: "essentials",
|
||||
Src: "https://github.com/zaiste/ansible-essentials",
|
||||
},
|
||||
{
|
||||
Name: "java",
|
||||
Src: "https://github.com/geerlingguy/ansible-role-java",
|
||||
Version: "origin/master",
|
||||
},
|
||||
{
|
||||
Name: "jenkins",
|
||||
Src: "https://github.com/geerlingguy/ansible-role-jenkins",
|
||||
Version: "4.2.1",
|
||||
},
|
||||
}
|
||||
rm := NewRequirements(rss...)
|
||||
t.Logf("\n%s", rm.String())
|
||||
}
|
||||
@@ -29,10 +29,11 @@ import (
|
||||
)
|
||||
|
||||
type Session struct {
|
||||
privateKey string
|
||||
playbook string
|
||||
inventory string
|
||||
files map[string][]byte
|
||||
privateKey string
|
||||
playbook string
|
||||
inventory string
|
||||
requirements string
|
||||
files map[string][]byte
|
||||
|
||||
outputWriter io.Writer
|
||||
stateMux *sync.Mutex
|
||||
@@ -63,6 +64,11 @@ func (sess *Session) Inventory(s string) *Session {
|
||||
return sess
|
||||
}
|
||||
|
||||
func (sess *Session) Requirements(s string) *Session {
|
||||
sess.requirements = s
|
||||
return sess
|
||||
}
|
||||
|
||||
func (sess *Session) AddFile(path string, data []byte) *Session {
|
||||
sess.files[path] = data
|
||||
return sess
|
||||
@@ -143,6 +149,17 @@ func (sess *Session) Run(ctx context.Context) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// write out requirements
|
||||
var requirements string
|
||||
if len(sess.requirements) > 0 {
|
||||
requirements = filepath.Join(tmpdir, "requirements.yml")
|
||||
err = ioutil.WriteFile(requirements, []byte(sess.requirements), os.FileMode(0600))
|
||||
if err != nil {
|
||||
err = errors.WithMessagef(err, "writing requirements %s", requirements)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// write out files
|
||||
for name, content := range sess.files {
|
||||
path := filepath.Join(tmpdir, name)
|
||||
@@ -167,6 +184,29 @@ func (sess *Session) Run(ctx context.Context) (err error) {
|
||||
}
|
||||
}()
|
||||
|
||||
// install required roles
|
||||
if len(requirements) > 0 {
|
||||
args := []string{
|
||||
"install", "-r", requirements,
|
||||
}
|
||||
cmd := exec.CommandContext(ctx, "ansible-galaxy", args...)
|
||||
stdout, _ := cmd.StdoutPipe()
|
||||
stderr, _ := cmd.StderrPipe()
|
||||
if err1 := cmd.Start(); err1 != nil {
|
||||
errs = append(errs, errors.WithMessage(err1, "start ansible-galaxy install roles"))
|
||||
return
|
||||
}
|
||||
// Mix stdout, stderr
|
||||
if sess.outputWriter != nil {
|
||||
go io.Copy(sess.outputWriter, stdout)
|
||||
go io.Copy(sess.outputWriter, stderr)
|
||||
}
|
||||
if err1 := cmd.Wait(); err1 != nil {
|
||||
errs = append(errs, errors.WithMessage(err1, "wait ansible-galaxy install roles"))
|
||||
}
|
||||
}
|
||||
|
||||
// run playbook
|
||||
{
|
||||
args := []string{
|
||||
"--inventory", inventory,
|
||||
|
||||
Reference in New Issue
Block a user