Skip to content
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

commands/operator-sdk: Add CLI support for Ansible Operator #486

Merged
merged 16 commits into from
Oct 2, 2018

Conversation

dymurray
Copy link
Contributor

@dymurray dymurray commented Sep 14, 2018

  • operator-sdk new --type ansible
  • operator-sdk build support. Autodetect type of operator by looking for watches.yaml
  • operator-sdk generate support.
  • [ ] operator-sdk up local support. Going to break this out to a separate PR

Copy link
Member

@shawn-hurley shawn-hurley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments even though this is WIP

if err != nil {
cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("failed to output build image %v: (%v)", image, string(o)))
}
fmt.Fprintln(os.Stdout, string(o))
}

func determineOperatorType() string {
if _, err := os.Stat(watchesYaml); err == nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dymurray I would prefer this to be if there is a go file in the cmd dir rather than if a watches file exists.

The reason is, if there is a go the main file, we should build that, if there is not then we assume ansible. This will be less error-prone and should handle other use cases like building a go operator but using some of the ansible operators.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the other hand, we probably shouldn't assume that the lack of go source means ansible. Other types, like perhaps helm, may not have go source either. It could be best to positively identify one or the other, and let the default be "error; no operator type detected".

Copy link
Member

@shawn-hurley shawn-hurley Sep 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering all that happens now, is a build of the dockerfile, that seems like the reasonable default IMO. If we add a third type we can deal with the differences then IMO.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to change this so that we first check for cmd/<name>/main.go and if we find it we build just like we expect for a normal golang operator except with the Ansible Operator Dockerfile.

newCmd.Flags().BoolVar(&skipGit, "skip-git-init", false, "Do not init the directory as a git repository")
newCmd.Flags().BoolVar(&generatePlaybook, "generate-playbook", false, "Generate a playbook skeleton in watches.yaml for Ansible Operator")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mention that this is only used for type ansible.

err := g.Render()
if err != nil {
cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("failed to create project %v: %v", projectName, err))
}
pullDep()
generate.K8sCodegen(projectName)
if operatorType == "go" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the second time we are comparing this value, might as well make it a constant?

pkg/generator/generator.go Show resolved Hide resolved
@dymurray dymurray changed the title [WIP] Add CLI support for Ansible Operator Add CLI support for Ansible Operator Sep 19, 2018
@openshift-ci-robot openshift-ci-robot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Sep 19, 2018
@dymurray dymurray changed the title Add CLI support for Ansible Operator [WIP] Add CLI support for Ansible Operator Sep 19, 2018
@openshift-ci-robot openshift-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Sep 19, 2018
@dymurray dymurray force-pushed the ansiblecli branch 2 times, most recently from 6df8bfe to d240c1e Compare September 20, 2018 20:34
@openshift-ci-robot openshift-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Sep 20, 2018
@dymurray dymurray changed the title [WIP] Add CLI support for Ansible Operator Add CLI support for Ansible Operator Sep 20, 2018
@openshift-ci-robot openshift-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Sep 20, 2018
Copy link
Member

@shawn-hurley shawn-hurley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dymurray I am wondering if we may want to create multiple generator(common/ansible/go) types with a Generator interface. This way we do not have switch statements in multiple places but rather a type that encapsulates generating that type.

WDYT?

/cc @hasbro17 @fanminshi @mhrivnak

crdCmd := &cobra.Command{
Use: "crd",
Short: "Generates a custom resource definition",
Long: `generates a custom resource definition (CRD) file for the .
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we missing the end of this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops... yes.

Version: version(apiVersion),
}
crdFilePath := filepath.Join(deployDir, strings.ToLower(kind) + "_crd.yaml")
return renderWriteFile(crdFilePath, crdFilePath, crdYamlTmpl, crdTd)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should create a cr.yaml for the new CRD as well, IMO.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok. i will update to add cr.yaml as well

return renderWriteFile(crdFilePath, crdFilePath, crdYamlTmpl, crdTd)
}

func renderDeployFiles(deployDir, projectName, apiVersion, kind, operatorType string) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should use the RenderDeployCrdFile IMO

fmt.Fprintln(os.Stdout, "Generating custom resource definition (CRD) file")

// Generate CRD file
if err := generator.RenderDeployCrdFile(apiVersion, kind); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to verify that we are in the project root when running this command? I am a little worried that we are not guarding against that, and could have some odd behavior for the user.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed. I've made an update to check for the ./deploy sub-directory

commands/operator-sdk/cmd/new.go Show resolved Hide resolved
@dymurray
Copy link
Contributor Author

dymurray commented Sep 21, 2018

@shawn-hurley That makes sense to me. Especially if operator-sdk is going to be expanded to encapsulate other types of operators. Some of these functions however I felt that it was useful to encapsulate everything in the same place. Rendering tmp was one example... but curious what others think as well.

newCmd.Flags().BoolVar(&skipGit, "skip-git-init", false, "Do not init the directory as a git repository")
newCmd.Flags().BoolVar(&generatePlaybook, "generate-playbook", false, "Generate a playbook skeleton in watches.yaml. (Only used for --type ansible)")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this say "and watches.yaml"? A playbook skeleton would be created separately on the filesystem, and then referenced from within watches.yaml. It may be confusing to say the skeleton of a playbook will be in watches.yaml.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Your wording is far more accurate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually... I'm going to remove and watches.yaml and just leave it at Generate a playbook skeleton since we always generate watches.yaml when --type ansible.

return err
}
default:
return errors.New(fmt.Sprintf("unexpected operator type [%v]", g.operatorType))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check out fmt.Errorf()

@dymurray
Copy link
Contributor Author

@johnkim76 You might be best to answer Shawn's questions above

@hasbro17
Copy link
Contributor

I am wondering if we may want to create multiple generator(common/ansible/go) types with a Generator interface. This way we do not have switch statements in multiple places but rather a type that encapsulates generating that type.

@shawn-hurley Yes we'll definitely need a more general generator/scaffolder.
Fanmin and I discussed this while thinking about the controller-runtime refactor.
We've held off on this right now but I kind of like the approach in controller-tools where they have a general scaffolding utility that can scaffold any kind of file based on the input struct(template+values+file-location).
https://github.com/kubernetes-sigs/controller-tools/blob/master/cmd/controller-scaffold/cmd/project.go#L86-L97
https://github.com/kubernetes-sigs/controller-tools/blob/master/pkg/scaffold/scaffold.go#L133-L179

Right now we're only coupling the templates and their inputs structs together and just generate each file individually i.e we don't use a generator, but we'll eventually have to add a more general layer to handle that for any kind of file().
e.g here's how we generate a file right now.
https://github.com/operator-framework/operator-sdk/blob/refactor/controller-runtime/pkg/scaffold/register.go
https://github.com/operator-framework/operator-sdk/blob/refactor/controller-runtime/commands/operator-sdk/cmd/add/api.go#L112-L121

With a more general generator/scaffolder we could just change the inputs (based on the CLI command and type of operator) and generate the necessary files.

But we'll have to think that through a bit more and not in this PR I think.

@johnkim76 johnkim76 force-pushed the ansiblecli branch 2 times, most recently from 529f74a to 5286eb3 Compare September 22, 2018 03:51
@dymurray
Copy link
Contributor Author

@shawn-hurley @hasbro17 In response to your comments, is there anything you'd like me to change about my implementation in the scaffolding logic? Or is this something that you'd like to address at a later time?

@shawn-hurley
Copy link
Member

I think @hasbro17 wants to deal with it later, so no changes.

@shawn-hurley shawn-hurley added the language/ansible Issue is related to an Ansible operator project label Sep 26, 2018
@shawn-hurley
Copy link
Member

@dymurray when you get a chance could you please rebase?

@dymurray dymurray force-pushed the ansiblecli branch 2 times, most recently from c371dcb to 310544f Compare September 26, 2018 20:23
@shawn-hurley shawn-hurley changed the title Add CLI support for Ansible Operator commands/operator-sdk: Add CLI support for Ansible Operator Sep 27, 2018
@fanminshi
Copy link
Contributor

lgtm after nits

@shawn-hurley
Copy link
Member

@hasbro17 was your review complete and does this now look good to you?

@hasbro17
Copy link
Contributor

hasbro17 commented Oct 1, 2018

@shawn-hurley Sorry I got busy with a couple of other reviews. I'll finish reviewing this today.

if err != nil {
cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("failed to build: (%v)", string(o)))
// Don't need to buld go code if Ansible Operator
if buildCmd() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change the name to be more representative of the actual function?
Right now it's just checking if cmd/<project-name>/main.go exists to determine if it's an Ansible or Go type project.
So perhaps mainExists() or isGoProject().

fmt.Fprintln(os.Stdout, "Generating custom resource definition (CRD) file")

// generate CRD file
wd, _ := os.Getwd()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check return error.

Short: "Generates a custom resource definition (CRD) and the custom resource (CR) files",
Long: `The operator-sdk generate command will create a custom resource definition (CRD) and the custom resource (CR) files for the specified api-version and kind.

Generated CRD filename: <project-name>/deploy/<kind>_crd.yaml
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shawn-hurley Just wanted to point out that if you try to generate a second CRD with the same Kind but different APIVersion then that will overwrite the previous <kind>_crd.yaml. Not sure if that's a legitimate use case in an ansible type project but we account for multiple CRDs in the refactor branch by using the format deploy/crds/<group>_<version>_<kind>_crd.yaml

https://github.com/operator-framework/operator-sdk/blob/refactor/controller-runtime/commands/operator-sdk/cmd/add/api.go#L146-L168

We'll soon add the changes from this PR into the refactor branch as well(to fit the style of the scaffold).
Right now we don't have a separate generate CRD command but I'm wondering if you wanted to make the CRD generation consistent with how we do it in the refactor branch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense to me... @johnkim76 any concerns around this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that sounds good. I'll make the update to the filename. thank you.

// │ │ └── <kind>
// │ ├── watches.yaml
// │ ├── deploy
// │ │ ├── <kind>-CRD.yaml
Copy link
Contributor

@hasbro17 hasbro17 Oct 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nit but unless I'm mistaken, operator-sdk new --type=ansible --api-version=<apiversion> --kind=<kind> will still generate:

// │   ├── deploy
// │   │   ├── crd.yaml
// │   │   ├── rbac.yaml
// │   │   ├── operator.yaml
// │   ├   └── cr.yaml

<kind>_crd.yaml and <kind>_cr.yaml are only generated by operator-sdk generate crd --kind --api-version.
See renderDeployFiles() below. Although that should still be fine I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@johnkim76 is this intended? Would you prefer that we change the new output to have the same filenames?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I think we should change the new behavior to have the <g>_<v>_<k>_cr.yaml and <g>_<v>_<k>_crd.yaml names.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@johnkim76 based on Shawn's comment below we are going to hold off on that for the refactoring.

func (g *Generator) renderRole() error {
fmt.Printf("Rendering Ansible Galaxy role [%v/%v/%v]...\n", g.projectName, rolesDir, g.kind)
agcmd := exec.Command(filepath.Join(g.projectName, galaxyInitCmd))
_, err := agcmd.CombinedOutput()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worth logging or returning the CombinedOutput here as well if the command fails.
The galaxyInit script might run but exit with an error. In which case the stdout and stderr might be more useful to see.
The err returned will just only say that the command exited with exit code 1.

@hasbro17
Copy link
Contributor

hasbro17 commented Oct 1, 2018

LGTM after nits.

@shawn-hurley We don't have to address the changes to the generate crd command right now but I thought I would just mention that we might have to change the output later on as we unify these changes with the layout from the refactor branch.

@dymurray
Copy link
Contributor Author

dymurray commented Oct 2, 2018

Thanks a lot for the feedback @hasbro17. @johnkim76 I would like your thoughts on the generate crd feedback provided. Not sure what you would prefer we do.

@shawn-hurley
Copy link
Member

@dymurray @johnkim76 I think that we can fix the filenames for the generation command now, and then deal with the new command in the refactor branch as @hasbro17 suggested.

I think this will work better because we shouldn't be changing new for everyone unless it is on the refactor branch IMO and fixing the CRD generation is new and shouldn't have expectations around it already.

Does this make sense to everyone?


// verifyCrdDeployPath checks if the path <project-name>/deploy sub-directory is exists, and that is rooted under $GOPATH
func verifyCrdDeployPath() {
// check if $GOPATH env exists
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While re-looking at the code, I would like to change one more thing about the generation as well

I think an ansible operator new, should not have to have Gopath set up. I think this would force users to have that, and I think we should avoid this.

@johnkim76 I wonder if we should just check that the current working dir has a deploy directory instead?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok.. I'll remove the check for the Gopath

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch Shawn. I agree we shouldn't depend on Go being configured.

Shawn Hurley and others added 5 commits October 2, 2018 10:03
…ator-framework#546)

* commands,pkg/test: support single namespace mode for local test

This commit brings support for running the tests in a single
namespace when using `test local`, which was previously only used
by `test cluster` (where it was a requirement to properly function)

* doc: update docs with new test local --namespace flag

* pkg/test/resource_creator.go: check namespace env value

* pkg/test: change handling of TestNamespaceEnv
…or-framework#548)

PR operator-framework#525 changed the way that dep worked to fix dependency issues
when doing e2e tests on travis. The PR breaks e2e testing on local
machines though, as the tests will just use the master branch
instead of a local branch. This commit symlinks the local sdk
into vendor on non-travis tests. The tests will still fail on local
machines if there is a dependency change, but we are unable to fix
this on local machines unless `dep` adds local repo support.
@openshift-ci-robot openshift-ci-robot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Oct 2, 2018
@hasbro17
Copy link
Contributor

hasbro17 commented Oct 2, 2018

@shawn-hurley Sounds good to me.

@shawn-hurley shawn-hurley merged commit a947a51 into operator-framework:master Oct 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
language/ansible Issue is related to an Ansible operator project size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants