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

_skaffold-init task multimodule logic issues #2262

Closed
balopat opened this issue Feb 1, 2020 · 6 comments · Fixed by #2263
Closed

_skaffold-init task multimodule logic issues #2262

balopat opened this issue Feb 1, 2020 · 6 comments · Fixed by #2263
Milestone

Comments

@balopat
Copy link

balopat commented Feb 1, 2020

The issues with the current logic (at least in the maven plugin, gradle task might have the same issues):

  • when a submodule has a different parent specified (e.g. spring boot starter pom) then our current logic fails to set the project id as the parent comes back as null in the InitMojo - this creates issues in multimodule projects (e.g. the Cloud Code java guestbook sample) because the listed projects don't have anything in them
  • I'm not sure how frequent nested modules are but currently we don't handle those well either
  • we are using the artifactId instead of the module name to return a project which is a problem as that is interpreted on the skaffold side as a directory

I won't have time to fully implement the thing with tests and everything, but as I played around with the code this seemed to do the job altogether:

@Mojo(name = InitMojo.GOAL_NAME, requiresDependencyCollection = ResolutionScope.NONE)
public class InitMojo extends JibPluginConfiguration {

  @VisibleForTesting static final String GOAL_NAME = "_skaffold-init";

  @Override
  public void execute() throws MojoExecutionException {
    checkJibVersion();
    MavenProject project = getProject();
    MavenProject topLevelProject = getSession().getTopLevelProject();
    if (!project.equals(topLevelProject)) {
      return;
    }

    if (isParentProject(project)) {
      Set<MavenProject> projects = collectLeafProjects(project);
      for (MavenProject p : projects) {
        print(p, true);
      }
    } else {
      print(project, false);
    }
  }

  private Set<MavenProject> collectLeafProjects(MavenProject project) {
    Set<MavenProject> projects = new HashSet<>();
    for (MavenProject p : project.getCollectedProjects()) {
      if (isParentProject(p)) {
        projects.addAll(collectLeafProjects(p));
      } else {
        projects.add(p);
      }
    }
    return projects;
  }

  private boolean isParentProject(MavenProject project) {
    return project.getPackaging().equals("pom") && project.getModules().size() > 0;
  }

  private void print(MavenProject project, boolean setProject) throws MojoExecutionException {
    SkaffoldInitOutput skaffoldInitOutput = new SkaffoldInitOutput();
    skaffoldInitOutput.setImage(getTargetImage());
    if (setProject) {
      skaffoldInitOutput.setProject(project.getGroupId() + ":" + project.getArtifactId());
    }
    System.out.println();
    System.out.println("BEGIN JIB JSON");
    try {
      System.out.println(skaffoldInitOutput.getJsonString());
    } catch (IOException ex) {
      throw new MojoExecutionException(ex.getMessage(), ex);
    }
  }
}
@balopat balopat changed the title _skaffold_init task multimodule logic is broken _skaffold_init task multimodule logic issues Feb 1, 2020
@balopat balopat changed the title _skaffold_init task multimodule logic issues _skaffold-init task multimodule logic issues Feb 1, 2020
@chanseokoh
Copy link
Member

Don't forget to check GoogleContainerTools/skaffold#2844

@TadCordle
Copy link
Contributor

TadCordle commented Feb 3, 2020

This seems like an improvement, but the problem now is that when the goal runs on a multi-module project, the goal runs on all of the sub-modules first before running on the parent. This means for the java-guestbook sample, which has a frontend and backend module, we get output like the following:

$ ./mvnw jib:_skaffold-init

// frontend prints
BEGIN JIB JSON
{}

// backend prints
BEGIN JIB JSON
{}

// parent prints
BEGIN JIB JSON
{"project":"org.springframework.boot:backend"}

BEGIN JIB JSON
{"project":"org.springframework.boot:frontend"}

I think the intended behavior is to only print the last 2 JSON structs, correct? It seems like the topLevelProject check at the top doesn't work.

@loosebazooka
Copy link
Member

should we force it to only run on the parent?

@TadCordle
Copy link
Contributor

Actually, my mistake. Was running the wrong version of Jib on the submodules. It looks like this does work.

@jonjohnsonjr
Copy link

For posterity, I'll chime in to say my issue is now fixed.

Before

$ skaffold init --XXenableJibInit --analyze | jq .
{
  "builders": [
    {
      "name": "Jib Maven Plugin",
      "payload": {
        "path": "pom.xml"
      }
    },
    {
      "name": "Jib Maven Plugin",
      "payload": {
        "path": "pom.xml"
      }
    },
    {
      "name": "Docker",
      "payload": {
        "path": "backend/Dockerfile"
      }
    },
    {
      "name": "Docker",
      "payload": {
        "path": "frontend/Dockerfile"
      }
    }
  ],
  "images": [
    {
      "name": "java-guestbook-backend",
      "foundMatch": false
    },
    {
      "name": "java-guestbook-frontend",
      "foundMatch": false
    },
    {
      "name": "mongo",
      "foundMatch": false
    }
  ]
}

After

$ skaffold init --XXenableJibInit --analyze | jq .
{
  "builders": [
    {
      "name": "Jib Maven Plugin",
      "payload": {
        "path": "pom.xml",
        "project": "org.springframework.boot:frontend"
      }
    },
    {
      "name": "Jib Maven Plugin",
      "payload": {
        "path": "pom.xml",
        "project": "org.springframework.boot:backend"
      }
    },
    {
      "name": "Docker",
      "payload": {
        "path": "backend/Dockerfile"
      }
    },
    {
      "name": "Docker",
      "payload": {
        "path": "frontend/Dockerfile"
      }
    }
  ],
  "images": [
    {
      "name": "java-guestbook-backend",
      "foundMatch": false
    },
    {
      "name": "java-guestbook-frontend",
      "foundMatch": false
    },
    {
      "name": "mongo",
      "foundMatch": false
    }
  ]
}

@chanseokoh
Copy link
Member

@balopat @jonjohnsonjr we've released Jib 2.1.0, which fixes this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants