-
Notifications
You must be signed in to change notification settings - Fork 14
Ecosystem implementation #3683
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ecosystem implementation #3683
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package runtime | ||
|
||
import "github.com/ActiveState/cli/pkg/buildplan" | ||
|
||
// eg. | ||
// availableEcosystems = []func() (ecosystem, error){ | ||
// func() (ecosystem, error) { | ||
// return &python.Ecosystem{}, nil | ||
// }, | ||
// } | ||
var availableEcosystems []func() ecosystem | ||
|
||
type ecosystem interface { | ||
Init(runtimePath string, buildplan *buildplan.BuildPlan) error | ||
Namespaces() []string | ||
Add(artifact *buildplan.Artifact, artifactSrcPath string) ([]string, error) | ||
Remove(artifact *buildplan.Artifact) error | ||
Apply() error | ||
} | ||
|
||
func artifactMatchesEcosystem(a *buildplan.Artifact, e ecosystem) bool { | ||
for _, namespace := range e.Namespaces() { | ||
for _, i := range a.Ingredients { | ||
if i.Namespace == namespace { | ||
return true | ||
} | ||
} | ||
} | ||
return false | ||
} | ||
|
||
func namespacesMatchesEcosystem(namespaces []string, e ecosystem) bool { | ||
for _, namespace := range e.Namespaces() { | ||
for _, n := range namespaces { | ||
if n == namespace { | ||
return true | ||
} | ||
} | ||
} | ||
return false | ||
} | ||
|
||
func filterEcosystemMatchingArtifact(artifact *buildplan.Artifact, ecosystems []ecosystem) ecosystem { | ||
for _, ecosystem := range ecosystems { | ||
if artifactMatchesEcosystem(artifact, ecosystem) { | ||
return ecosystem | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func filterEcosystemsMatchingNamespaces(ecosystems []ecosystem, namespaces []string) []ecosystem { | ||
result := []ecosystem{} | ||
for _, ecosystem := range ecosystems { | ||
if namespacesMatchesEcosystem(namespaces, ecosystem) { | ||
result = append(result, ecosystem) | ||
} | ||
} | ||
return result | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -68,6 +68,7 @@ type setup struct { | |
path string | ||
opts *Opts | ||
depot *depot | ||
ecosystems []ecosystem | ||
supportsHardLinks bool | ||
env *envdef.Collection | ||
buildplan *buildplan.BuildPlan | ||
|
@@ -90,7 +91,7 @@ type setup struct { | |
toInstall buildplan.ArtifactIDMap | ||
|
||
// toUninstall encompasses all artifacts that will need to be uninstalled for this runtime. | ||
toUninstall map[strfmt.UUID]struct{} | ||
toUninstall map[strfmt.UUID]bool | ||
} | ||
|
||
func newSetup(path string, bp *buildplan.BuildPlan, env *envdef.Collection, depot *depot, opts *Opts) (*setup, error) { | ||
|
@@ -127,10 +128,10 @@ func newSetup(path string, bp *buildplan.BuildPlan, env *envdef.Collection, depo | |
|
||
// Identify which artifacts we can uninstall | ||
installableArtifactsMap := installableArtifacts.ToIDMap() | ||
artifactsToUninstall := map[strfmt.UUID]struct{}{} | ||
artifactsToUninstall := map[strfmt.UUID]bool{} | ||
for id := range installedArtifacts { | ||
if _, required := installableArtifactsMap[id]; !required { | ||
artifactsToUninstall[id] = struct{}{} | ||
artifactsToUninstall[id] = true | ||
} | ||
} | ||
|
||
|
@@ -167,6 +168,16 @@ func newSetup(path string, bp *buildplan.BuildPlan, env *envdef.Collection, depo | |
} | ||
} | ||
|
||
// Load all ecosystems | ||
var ecosystems []ecosystem | ||
for _, e := range availableEcosystems { | ||
ecosystem := e() | ||
if err := ecosystem.Init(path, bp); err != nil { | ||
return nil, errs.Wrap(err, "Could not create ecosystem") | ||
} | ||
ecosystems = append(ecosystems, ecosystem) | ||
} | ||
|
||
return &setup{ | ||
path: path, | ||
opts: opts, | ||
|
@@ -179,6 +190,7 @@ func newSetup(path string, bp *buildplan.BuildPlan, env *envdef.Collection, depo | |
toUnpack: artifactsToUnpack.ToIDMap(), | ||
toInstall: artifactsToInstall.ToIDMap(), | ||
toUninstall: artifactsToUninstall, | ||
ecosystems: ecosystems, | ||
}, nil | ||
} | ||
|
||
|
@@ -269,11 +281,18 @@ func (s *setup) update() error { | |
} | ||
} | ||
|
||
// Tell applicable ecosystems to perform any final uninstall actions. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not convinced we can have Feel free to correct me on this. |
||
for _, e := range s.ecosystems { | ||
if err := e.Apply(); err != nil { | ||
return errs.Wrap(err, "Could not apply ecosystem changes") | ||
} | ||
} | ||
|
||
// Install artifacts | ||
wp = workerpool.New(maxConcurrency) | ||
for _, a := range s.toInstall { | ||
wp.Submit(func() error { | ||
if err := s.install(a.ArtifactID); err != nil { | ||
if err := s.install(a); err != nil { | ||
return errs.Wrap(err, "Could not install artifact") | ||
} | ||
return nil | ||
|
@@ -285,6 +304,13 @@ func (s *setup) update() error { | |
return errs.Wrap(err, "errors occurred during install") | ||
} | ||
|
||
// Tell applicable ecosystems to perform any final install actions. | ||
for _, e := range s.ecosystems { | ||
if err := e.Apply(); err != nil { | ||
return errs.Wrap(err, "Could not apply ecosystem changes") | ||
} | ||
} | ||
|
||
if err := s.postProcess(); err != nil { | ||
return errs.Wrap(err, "Postprocessing failed") | ||
} | ||
|
@@ -447,7 +473,8 @@ func (s *setup) updateExecutors() error { | |
return nil | ||
} | ||
|
||
func (s *setup) install(id strfmt.UUID) (rerr error) { | ||
func (s *setup) install(artifact *buildplan.Artifact) (rerr error) { | ||
id := artifact.ArtifactID | ||
defer func() { | ||
if rerr == nil { | ||
if err := s.fireEvent(events.ArtifactInstallSuccess{id}); err != nil { | ||
|
@@ -465,6 +492,20 @@ func (s *setup) install(id strfmt.UUID) (rerr error) { | |
} | ||
|
||
artifactDepotPath := s.depot.Path(id) | ||
|
||
if ecosys := filterEcosystemMatchingArtifact(artifact, s.ecosystems); ecosys != nil { | ||
files, err := ecosys.Add(artifact, artifactDepotPath) | ||
if err != nil { | ||
return errs.Wrap(err, "Ecosystem unable to add artifact") | ||
} | ||
s.depot.Track(id, &deployment{ | ||
Type: deploymentTypeEcosystem, | ||
Path: filepath.Join(s.path, artifact.ArtifactID.String()), // dummy path for uniqueness | ||
Files: files, | ||
}) | ||
return nil | ||
} | ||
|
||
envDef, err := s.env.Load(artifactDepotPath) | ||
if err != nil { | ||
return errs.Wrap(err, "Could not get env") | ||
|
@@ -506,6 +547,17 @@ func (s *setup) uninstall(id strfmt.UUID) (rerr error) { | |
} | ||
|
||
artifactDepotPath := s.depot.Path(id) | ||
|
||
// TODO: CP-956 | ||
//if ecosys := filterEcosystemMatchingArtifact(artifact, s.ecosystems); ecosys != nil { | ||
// err := ecosys.Remove(artifact) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The depot does not have enough information to construct an |
||
// if err != nil { | ||
// return errs.Wrap(err, "Ecosystem unable to remove artifact") | ||
// } | ||
// s.depot.Untrack(id, filepath.Join(s.path, artifact.ArtifactID.String())) | ||
// return nil | ||
//} | ||
|
||
envDef, err := s.env.Load(artifactDepotPath) | ||
if err != nil { | ||
return errs.Wrap(err, "Could not get env") | ||
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The depot does not have enough information to construct a
buildplan.Artifact
object. The depot only tracks artifact IDs, and we infer what artifacts to uninstall by IDs that do not exist in the incoming buildplan. I am changing fromstruct{}
tobool
to better reflect this for now, as it was a source of confusion.CP-956, which is to implement
Remove()
andUntrack()
should hopefully figure out how best to accomplish what we want.