Monday, April 23, 2018

Wildfly: deploy an application as a root context

http://www.mastertheboss.com/jboss-web/jbosswebserver/how-to-deploy-a-web-application-on-the-root-context-on-jboss-as-7


Schemas for the standalone.xml can be found in D:\apps\wildfly12\docs\schema

For the undertow (former web) subsystem, use wildfly-undertow_5_0.xsd



and the virtual-server is defined in jboss-as-web_2_2.xsd (which is JBoss AS, not Wildfly)


This CLI:
/subsystem=undertow:write-attribute(name=default-virtual-host, value=default-host)
adds default-virtual-host="default-host" to the line subsystem xmlns="urn:jboss:domain:undertow:5.0" in config.xml

subsystem xmlns="urn:jboss:domain:undertow:5.0"




Very helpful: https://docs.jboss.org/author/display/WFLY10/CLI+Recipes


By default, Wildfly 12 comes with this Undertow configuration

<subsystem xmlns="urn:jboss:domain:undertow:5.0">
 <buffer-cache name="default"/>
 <server name="default-server">
  <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
  <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
  <host name="default-host" alias="localhost">
   <location name="/" handler="welcome-content"/>
   <filter-ref name="server-header"/>
   <filter-ref name="x-powered-by-header"/>
   <http-invoker security-realm="ApplicationRealm"/>
  </host>
 </server>
 <servlet-container name="default">
  <jsp-config/>
  <websockets/>
 </servlet-container>
 <handlers>
  <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
 </handlers>
 <filters>
  <response-header name="server-header" header-name="Server" header-value="WildFly/11"/>
  <response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>
 </filters>
</subsystem>


According to the book "WildFly Configuration, Deployment, and Administration - Second Edition" , page 118, if you want to deploy a webapp to handle the / root context, you first have to run this CLI:


/subsystem=undertow/server=default-server/host=default-host/location=\/:remove()

After which the entry <location name="/" handler="welcome-content"/> will disappear from the standalone.xml

To build such CLI command, it's very useful to open the Administration console, then bottom right you have "Tools" "Management Model" , then you navigate in the tree matching the structure you can read in the XML.
Unfortunately CLI can't be generated directly from the console (as it was the case in WLST and WebLogic! One huge point in favor of WebLogic!)

<jboss-web>
<context-root>/</context-root>
</jboss-web>

git clone https://github.com/vernetto/primefaces-test.git
cd primefaces-test
mvn clean package

(in the CLI) deploy c:\pierre\gitclones\primefaces-test\target\primefaces-test-1.0-SNAPSHOT.war


enter localhost:8080 and your webapp is there instead of the ROOT.war application !

Enter http://localhost:9990/console/App.html#standalone-deployments;backButton=/deployments-details and you see the









Sunday, April 22, 2018

wildfly configuration, deployment and administration - second edition


This is an excellent book, hands on and very practical. Good for the beginner just getting started with Wildfly.



Friday, April 20, 2018

h2 remote TCP client

telnet ip port

Remote connections to this server are not allowed, see -tcpAllowOthers
org.h2.jdbc.JdbcSQLException: Remote connections to this server are not allowed, see -tcpAllowOthers [90117-197]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:357)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.message.DbException.get(DbException.java:144)
at org.h2.server.TcpServerThread.run(TcpServerThread.java:89)
at java.lang.Thread.run(Thread.java:748)
Connection closed by foreign host.


You fix the issue by running h2 server as:

java -cp "/opt/h2/bin/h2-1.4.197.jar:$H2DRIVERS:$CLASSPATH" -Dh2.consoleTimeout=500000 org.h2.tools.Console -web -webAllowOthers -tcp -tcpAllowOthers


on the client side, in wildfly, you have

<datasource jndi-name="java:jboss/datasources/DOICHDS" pool-name="DOICHDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:tcp://yourserverip:9092/~/PIPPO;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>PIPPO</user-name>
<password>PIPPO</password>
</security>
</datasource>

See https://stackoverflow.com/a/9838282/651288



jboss-cli

https://docs.jboss.org/author/display/WFLY/Command+Line+Interface

$ ./jboss-cli.sh



Unable to read the logging configuration from 'file:/d/apps/wildfly12/bin/jboss-cli-logging.properties' (java.io.FileNotFoundException: \d\apps\wildfly12\bin\jboss-cli-logging.properties (The system cannot find the path specified))
INFO  [org.jboss.modules] JBoss Modules version 1.7.0.Final
INFO  [org.jboss.as.cli.CommandContext] You are disconnected at the moment. Type 'connect' to connect to the server or 'help' for the list of supported commands.
You are disconnected at the moment. Type 'connect' to connect to the server or 'help' for the list of supported commands.
[disconnected /] connect
connect
INFO  [org.xnio] XNIO version 3.6.2.Final
INFO  [org.xnio.nio] XNIO NIO Implementation Version 3.6.2.Final
INFO  [org.jboss.remoting] JBoss Remoting version 5.0.5.Final
INFO  [org.jboss.threads] JBoss Threads version 2.3.1.Final
INFO  [org.wildfly.security] ELY00001: WildFly Elytron version 1.2.2.Final
ERROR [org.jboss.as.cli.CommandContext] The controller is not available at localhost:9990: java.net.ConnectException: WFLYPRT0053: Could not connect to remote+http://localhost:9990. The connection failed: WFLYPRT0053: Could not connect to remote+http://localhost:9990. The connection failed: Connection refused: no further information
The controller is not available at localhost:9990: java.net.ConnectException: WFLYPRT0053: Could not connect to remote+http://localhost:9990. The connection failed: WFLYPRT0053: Could not connect to remote+http://localhost:9990. The connection failed: Connection refused: no further information



Instead of the normal ports 8080/9990 I have 8180/10090 , because in standalone.xml I have specified in socket-binding-group a jboss.socket.binding.port-offset:100

So I try with

./jboss-cli.sh --controller=localhost:10090

and I get a beautiful

INFO  [org.xnio] XNIO version 3.6.2.Final
INFO  [org.xnio.nio] XNIO NIO Implementation Version 3.6.2.Final
INFO  [org.jboss.remoting] JBoss Remoting version 5.0.5.Final
INFO  [org.jboss.threads] JBoss Threads version 2.3.1.Final
INFO  [org.wildfly.security] ELY00001: WildFly Elytron version 1.2.2.Final
[standalone@localhost:10090 /]



If you look in jboss-cli.xml you see that the default controller is configured in it:

<!-- The default controller to connect to when 'connect' command is executed w/o arguments -->
    <default-controller>
        <protocol>remote+http</protocol>
        <host>localhost</host>
        <port>9990</port>
    </default-controller>

If I change 9990 to 10090, I can seamlessly connect without having to specify the --controller=localhost:10090

Remarkable also the .jbossclirc file. "# WildFly (JBoss) CLI will execute commands from this file before
# the command line session (interactive or not) will start."


Regarding the message "Unable to read the logging configuration from 'file:/d/apps/wildfly12/bin/jboss-cli-logging.properties' ", I have it only when running the jboss-cli.sh in git bash.... if I run jboss-cli.bat I don't have the problem. Most likely it's due to the fact that in git bash the $JBOSS_HOME is rendered as file:/d/apps/wildfly12/ , and Java can't handle this... welcome to the messy world of Windows...


It seems also that the TAB autocomplete is not working under git bash.... I am switching permanently to a DOS console.... how sad..



Wednesday, April 18, 2018

RHEL SELinux and docker search behind a company firewall

It seems you should add registry.access.redhat.com to the company open firewall rules / iptables...

docker search hello-world

Error response from daemon: invalid registry endpoint https://registry.access.redhat.com/v1/: Get https://registry.access.redhat.com/v1/_ping: dial tcp: lookup registry.access.redhat.com on 127.0.0.1:53: no such host. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry registry.access.redhat.com` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/registry.access.redhat.com/ca.crt

https://rhelblog.redhat.com/2015/04/15/understanding-the-changes-to-docker-search-and-docker-pull-in-red-hat-enterprise-linux-7-1/


"The Red Hat default config in ‘/etc/sysconfig/docker’ adds ‘registry.access.redhat.com’, which is the authoritative source for official Red Hat content. The default docker.io search path is hardcoded and remains enabled."


eg:

cat /etc/sysconfig/docker
# /etc/sysconfig/docker

# Modify these options if you want to change the way the docker daemon runs
OPTIONS='--selinux-enabled --log-driver=journald --signature-verification=false'
if [ -z "${DOCKER_CERT_PATH}" ]; then
    DOCKER_CERT_PATH=/etc/docker
fi

# Do not add registries in this file anymore. Use /etc/containers/registries.conf
# from the atomic-registries package.
#

# On an SELinux system, if you remove the --selinux-enabled option, you
# also need to turn on the docker_transition_unconfined boolean.
# setsebool -P docker_transition_unconfined 1

# Location used for temporary files, such as those created by
# docker load and build operations. Default is /var/lib/docker/tmp
# Can be overriden by setting the following environment variable.
# DOCKER_TMPDIR=/var/tmp

# Controls the /etc/cron.daily/docker-logrotate cron job status.
# To disable, uncomment the line below.
# LOGROTATE=false

# docker-latest daemon can be used by starting the docker-latest unitfile.
# To use docker-latest client, uncomment below lines
#DOCKERBINARY=/usr/bin/docker-latest
#DOCKERDBINARY=/usr/bin/dockerd-latest
#DOCKER_CONTAINERD_BINARY=/usr/bin/docker-containerd-latest
#DOCKER_CONTAINERD_SHIM_BINARY=/usr/bin/docker-containerd-shim-latest


and

cat /etc/containers/registries.conf
# This is a system-wide configuration file used to
# keep track of registries for various container backends.
# It adheres to TOML format and does not support recursive
# lists of registries.

# The default location for this configuration file is /etc/containers/registries.conf.

# The only valid categories are: 'registries.search', 'registries.insecure', 
# and 'registries.block'.

[registries.search]
registries = ['registry.access.redhat.com']

# If you need to access insecure registries, add the registry's fully-qualified name.
# An insecure registry is one that does not have a valid SSL certificate or only does HTTP.
[registries.insecure]
registries = []


# If you need to block pull access from a registry, uncomment the section below
# and add the registries fully-qualified name.
#
# Docker only
[registries.block]
registries = []




docker registry-mirrors

One can setup a registry mirror to intercept all "docker pull" and route them through a local cache registry..... however there seem to be issues when you use Nexus Docker Repo for this purpose...

setup Nexus Docker registry as here http://www.javamonamour.org/2018/03/using-nexus-3-as-docker-registry-proxy.html


cat /etc/docker/daemon.json
{
"debug" : true,
"experimental" : true,
"insecure-registries" : [ "localhost:8081", "localhost:8082" ],
"registry-mirrors" : [
"http://localhost:8082"
]
}

sudo systemctl daemon-reload
sudo systemctl restart docker


docker start nexus3
docker login localhost:8082 (admin/admin123)

docker info
Registry Mirrors:
http://localhost:8082/

docker pull hello-world

sudo cat /var/log/messages | grep docker

Apr 17 22:35:02 localhost dockerd: time="2018-04-17T22:35:02.139328745+02:00" level=debug msg="Calling GET /v1.37/images/json"
Apr 17 22:35:14 localhost dockerd: time="2018-04-17T22:35:14.623910991+02:00" level=debug msg="Calling GET /_ping"
Apr 17 22:35:14 localhost dockerd: time="2018-04-17T22:35:14.628661368+02:00" level=debug msg="Calling GET /v1.37/info"
Apr 17 22:35:14 localhost dockerd: time="2018-04-17T22:35:14.673297720+02:00" level=debug msg="Calling POST /v1.37/images/create?fromImage=hello-world&tag=latest"
Apr 17 22:35:14 localhost dockerd: time="2018-04-17T22:35:14.673784263+02:00" level=debug msg="Trying to pull hello-world from http://localhost:8082/ v2"
Apr 17 22:35:15 localhost dockerd: time="2018-04-17T22:35:15.137325587+02:00" level=info msg="Attempting next endpoint for pull after error: Get http://localhost:8082/v2/library/hello-world/manifests/latest: no basic auth credentials"
Apr 17 22:35:15 localhost dockerd: time="2018-04-17T22:35:15.137404591+02:00" level=debug msg="Trying to pull hello-world from https://registry-1.docker.io v2"
Apr 17 22:35:17 localhost dockerd: time="2018-04-17T22:35:17.637206822+02:00" level=debug msg="Pulling ref from V2 registry: hello-world:latest"
Apr 17 22:35:17 localhost dockerd: time="2018-04-17T22:35:17.640510754+02:00" level=debug msg="docker.io/library/hello-world:latest resolved to a manifestList object with 9 entries; looking for a linux/amd64 match"
Apr 17 22:35:17 localhost dockerd: time="2018-04-17T22:35:17.640582612+02:00" level=debug msg="found match for linux/amd64 with media type application/vnd.docker.distribution.manifest.v2+json, digest sha256:d5c74e6f8efc7bdf42a5e22bd764400692cf82360d86b8c587a7584b03f51520"
Apr 17 22:35:18 localhost dockerd: time="2018-04-17T22:35:18.504407966+02:00" level=debug msg="pulling blob \"sha256:9bb5a5d4561a5511fa7f80718617e67cf2ed2e6cdcd02e31be111a8d0ac4d6b7\""
Apr 17 22:35:19 localhost dockerd: time="2018-04-17T22:35:19.580697501+02:00" level=debug msg="Downloaded 9bb5a5d4561a to tempfile /var/lib/docker/tmp/GetImageBlob741769005"
Apr 17 22:35:19 localhost dockerd: time="2018-04-17T22:35:19.600499679+02:00" level=debug msg="Applying tar in /var/lib/docker/overlay2/6fd7cd727232306d47dbbd8835c85bab265bc3c51f1fd4e784d814556652d761/diff"
Apr 17 22:35:19 localhost dockerd: time="2018-04-17T22:35:19.759362924+02:00" level=debug msg="Applied tar sha256:2b8cbd0846c5aeaa7265323e7cf085779eaf244ccbdd982c4931aef9be0d2faf to 6fd7cd727232306d47dbbd8835c85bab265bc3c51f1fd4e784d814556652d761, size: 1848"


Interesting this message:

Apr 17 22:35:15 localhost dockerd: time="2018-04-17T22:35:15.137325587+02:00" level=info msg="Attempting next endpoint for pull after error: Get http://localhost:8082/v2/library/hello-world/manifests/latest: no basic auth credentials"




https://github.com/moby/moby/issues/20097
https://stackoverflow.com/questions/42143395/docker-registry-mirror-not-used no basic auth credentials -> solution with nginx
https://github.com/moby/moby/issues/30880 this is the main ticket


it seems that the only workaround is to setup a nginx proxy with basic authentication injected
Otherwise, https://github.com/moby/moby/issues/30880 "Nexus OSS 3.6.0-02 can finally transparently proxy docker images. It has a new feature called "Anonymous Read Access" for docker registry access (see
https://help.sonatype.com/display/NXRM3/Private+Registry+for+Docker) and disabling "Force basic authentication" and adding "Docker bearer token realm" in nexus/admin/security/realms seems to fixes this issue, no more "no basic auth credentials" in the logfile."



I have done the above, and I can now see after a "docker pull hello-world":

Apr 18 15:01:24 localhost dockerd: time="2018-04-18T15:01:24.245724948+02:00" level=debug msg="Calling GET /_ping"
Apr 18 15:01:24 localhost dockerd: time="2018-04-18T15:01:24.246891099+02:00" level=debug msg="Calling GET /v1.37/info"
Apr 18 15:01:24 localhost dockerd: time="2018-04-18T15:01:24.362426987+02:00" level=debug msg="Calling POST /v1.37/images/create?fromImage=hello-world&tag=latest"
Apr 18 15:01:24 localhost dockerd: time="2018-04-18T15:01:24.374842745+02:00" level=debug msg="Trying to pull hello-world from http://localhost:8082/ v2"
Apr 18 15:01:24 localhost dockerd: time="2018-04-18T15:01:24.439398678+02:00" level=debug msg="Increasing token expiration to: 60 seconds"
Apr 18 15:01:29 localhost dockerd: time="2018-04-18T15:01:29.026052252+02:00" level=debug msg="Pulling ref from V2 registry: hello-world:latest"





Tuesday, April 17, 2018

Docker run a command in an image

How many times you are baffled because you run

docker run myregistry/maven:3-alpine

and it simply exists without doing anything.

Then you do

docker run myregistry/maven:3-alpine /bin/bash

and the same thing happens

Then you inspect the image:

docker image inspect myregistry/maven:3-alpine


and you notice

           "Cmd": [
                "mvn"
            ],

          "Entrypoint": [
                "/usr/local/bin/mvn-entrypoint.sh"
            ],


and you wonder what is actually executed....

Luckily you can simply OVERRIDE the entrypoint (see https://gist.github.com/mitchwongho/11266726 ) :


docker run -it --entrypoint /bin/bash myregistry/maven:3-alpine

so you enter directly a bash shell, without executing the original Entrypoint of course.


The documentation of this precious Maven image is https://hub.docker.com/_/maven/ here

mvn settings are in /usr/share/maven/ref/settings-docker.xml and (maybe) in /usr/share/maven/conf/settings.xml
mvn binaries are in /usr/bin/mvn -> /usr/share/maven/bin/mvn


Ref: docker run https://docs.docker.com/engine/reference/commandline/run/#options


Priceless, to debug Maven: mvn -X help:effective-settings



Monday, April 16, 2018

Jenkins sucks

Jenkins sucks. Ok it could suck more, but let me tell you what I find really frustrating from a begginner's perspective

a) documentation is pathetic. The Jenkins User Handbook until a few months ago was full of empty sections with only "work in progress".... now it's a bit better, but still....

b) plugins is a cosmic chaos... any basic installation would include at least some 100 common plugins, so why not include them in the Jenkins baseline and avoid all this chaos.... also, plugin documentation is most of the time really basic

c) no development IDE, no way to remote debug. Should I develop code in BlueOcean plugin in a browser??? are you serious??? When one is used to IntelliJ, having to code Jenkins Pipelines in Notepad++ is like going back to Stone Age. The Eclipse plugin is laughable, you can just remotely invoke the linter for validation.... no autocomplete, no inline javadoc, NOTHING

d) Groovy is good, but management of libraries is a bit shaky.... however this is not the weakest point, at least they don't make me code in XML like Maven or Ant do, or in a ridiculous DSL like Puppet does....

e) the UI was coded by children... you have to click for hours to find something... not even a search tool to point you quickly where a certain parameter is defined.... it's the typical click-o-drome of tools that are designed for non-programmers and end up being a nightmare of clicks and hidden corners.




Wednesday, April 11, 2018

debug hanging shell scripts

https://stackoverflow.com/questions/4640794/a-running-bash-script-is-hung-somewhere-can-i-find-out-what-line-it-is-on

set -x

lsof -p $pid

strace -p $pid -s 1024

/proc/$pid/environ

pstree -pl 21156 + cat /proc/15232/stack (15232 is the PID of the hanging process)

top

set -v or set -o verbose

http://bashdb.sourceforge.net/
https://www.shellcheck.net/
https://marketplace.visualstudio.com/items?itemName=rogalmic.bash-debug



Hibernate validator dependencies for unit testing

http://hibernate.org/validator/ home page of validation


at javax.validation.Validation$GenericBootstrapImpl.configure(Validation.java:271)
at javax.validation.Validation.buildDefaultValidatorFactory(Validation.java:110)
javax.validation.ValidationException: Unable to create a Configuration, because no Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath


I have this in my pom.xml

<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<scope>provided</scope>
</dependency>





Apparently I should add this implementation

<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.7.Final</version>
</dependency>


I do that, then I have :


java.lang.NoClassDefFoundError: javax/validation/ClockProvider
 at org.hibernate.validator.HibernateValidator.createGenericConfiguration(HibernateValidator.java:33)
 at javax.validation.Validation$GenericBootstrapImpl.configure(Validation.java:276)
 at javax.validation.Validation.buildDefaultValidatorFactory(Validation.java:110)

Caused by: java.lang.ClassNotFoundException: javax.validation.ClockProvider
 at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:357)





Then I add

<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
<scope>test</scope>
</dependency>




and I get

Caused by: java.lang.ClassNotFoundException: javax.validation.ParameterNameProvider


Here they say you should remove the validation-api : https://stackoverflow.com/questions/24652753/java-lang-noclassdeffounderror-javax-validation-parameternameprovider


I do this:


<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
<scope>test</scope>
</dependency>


now I get:



Caused by: javax.validation.ValidationException: HV000183: Unable to initialize 'javax.el.ExpressionFactory'. Check that you have the EL dependencies on the classpath, or use ParameterMessageInterpolator instead
 at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.buildExpressionFactory(ResourceBundleMessageInterpolator.java:123)
 at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.(ResourceBundleMessageInterpolator.java:47)
 at org.hibernate.validator.internal.engine.ConfigurationImpl.getDefaultMessageInterpolator(ConfigurationImpl.java:461)
 at org.hibernate.validator.internal.engine.ConfigurationImpl.getDefaultMessageInterpolatorConfiguredWithClassLoader(ConfigurationImpl.java:637)
 at org.hibernate.validator.internal.engine.ConfigurationImpl.getMessageInterpolator(ConfigurationImpl.java:388)
 at org.hibernate.validator.internal.engine.ValidatorFactoryImpl.(ValidatorFactoryImpl.java:179)
 at org.hibernate.validator.HibernateValidator.buildValidatorFactory(HibernateValidator.java:38)
 at org.hibernate.validator.internal.engine.ConfigurationImpl.buildValidatorFactory(ConfigurationImpl.java:355)
 at javax.validation.Validation.buildDefaultValidatorFactory(Validation.java:103)




So I add ( https://stackoverflow.com/questions/24386771/javax-validation-validationexception-hv000183-unable-to-load-javax-el-express )



<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.4</version>
<scope>test</scope>
</dependency>



and I get

java.lang.ClassNotFoundException: javax.el.ELManager


then I finally use

<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>


and it works!

once more, all you need is:

  <dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <scope>provided</scope>
  </dependency>

  <dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.7.Final</version>
    <scope>test</scope>
  </dependency>

  <dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.1.Final</version>
    <scope>test</scope>
  </dependency>

<dependency>
  <groupId>javax.el</groupId>
  <artifactId>javax.el-api</artifactId>
  <version>3.0.0</version>
    <scope>test</scope>
</dependency>

  <dependency>
    <groupId>org.glassfish.web</groupId>
    <artifactId>javax.el</artifactId>
    <version>2.2.4</version>
    <scope>test</scope>
  </dependency>
  















Saturday, April 7, 2018

H2 autogenerating unique IDs from Sequence

if you have annotated the ID with

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Entity;

@Entity
@Table(uniqueConstraints = @UniqueConstraint(columnNames = "ID"), name = "VOCABULARY")
public class Vocabulary implements Serializable {

@Id
@GeneratedValue
private Long id;

and declared the ID as
CREATE TABLE "VOCABULARY" (
    "ID" NUMBER(10,0) NOT NULL
...
)
CREATE UNIQUE INDEX "VOCABULARY_UNIQ_ID" ON "VOCABULARY" ("ID") ;
ALTER TABLE "VOCABULARY" ADD PRIMARY KEY ("ID");

this is not enough... you will get this when you try to insert a new record:

org.h2.jdbc.JdbcSQLException: Sequence "HIBERNATE_SEQUENCE" not found; SQL statement:
call next value for hibernate_sequence [90036-197]
        at org.h2.message.DbException.getJdbcSQLException(DbException.java:357)
        at org.h2.message.DbException.get(DbException.java:179)
        at org.h2.message.DbException.get(DbException.java:155)
        at org.h2.command.Parser.readSequence(Parser.java:5970)
        at org.h2.command.Parser.readTerm(Parser.java:3131)
        at org.h2.command.Parser.readFactor(Parser.java:2587)
        at org.h2.command.Parser.readSum(Parser.java:2574)
        at org.h2.command.Parser.readConcat(Parser.java:2544)
        at org.h2.command.Parser.readCondition(Parser.java:2370)
        at org.h2.command.Parser.readAnd(Parser.java:2342)
        at org.h2.command.Parser.readExpression(Parser.java:2334)
        at org.h2.command.Parser.parseCall(Parser.java:4854)
        at org.h2.command.Parser.parsePrepared(Parser.java:382)
        at org.h2.command.Parser.parse(Parser.java:335)
        at org.h2.command.Parser.parse(Parser.java:307)
        at org.h2.command.Parser.prepareCommand(Parser.java:278)
        at org.h2.engine.Session.prepareLocal(Session.java:611)
        at org.h2.server.TcpServerThread.process(TcpServerThread.java:271)
        at org.h2.server.TcpServerThread.run(TcpServerThread.java:165)
        at java.lang.Thread.run(Thread.java:748)

        at org.h2.engine.SessionRemote.done(SessionRemote.java:624)
        at org.h2.command.CommandRemote.prepare(CommandRemote.java:68)
        at org.h2.command.CommandRemote.(CommandRemote.java:45)
        at org.h2.engine.SessionRemote.prepareCommand(SessionRemote.java:494)
        at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1203)
        at org.h2.jdbc.JdbcPreparedStatement.(JdbcPreparedStatement.java:73)
        at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:676)
        at org.jboss.jca.adapters.jdbc.BaseWrapperManagedConnection.doPrepareStatement(BaseWrapperManagedConnection.java:757)
        at org.jboss.jca.adapters.jdbc.BaseWrapperManagedConnection.prepareStatement(BaseWrapperManagedConnection.java:743)
        at org.jboss.jca.adapters.jdbc.WrappedConnection.prepareStatement(WrappedConnection.java:454)
        at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$1.doPrepare(StatementPreparerImpl.java:87)
        at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)



Solution is:

CREATE SEQUENCE VOCABULARY_SEQUENCE_ID START WITH (select max(ID) + 1 from VOCABULARY);

(this allows me to prepopulate the VOCABULARY with static values, and initialize the sequence accordingly)

and in Java

@Id
@SequenceGenerator(name= "VOCABULARY_SEQUENCE", sequenceName = "VOCABULARY_SEQUENCE_ID", initialValue=1, allocationSize = 1)
@GeneratedValue(strategy=GenerationType.AUTO, generator="VOCABULARY_SEQUENCE")
private Long id;



Why in 2018 such common things have to be still so complicated, no clue, something is really going wrong in the Java world... maybe using Spring it's only a matter of 1 annotation... no clue...





ANTLR

http://www.antlr.org/




Source code: https://pragprog.com/titles/tpantlr2/source_code

(I am using GIT bash)
on Windows:
export CLASSPATH=/d/pierre/downloads/antlr/antlr-4.0-complete.jar:.
alias antlr="java -jar /d/pierre/downloads/antlr/antlr-4.0-complete.jar"
alias grun='java org.antlr.v4.runtime.misc.TestRig'

on Linux
export CLASSPATH=/home/centos/antlr/antlr-4.0-complete.jar:.
alias grun='java -cp /home/centos/antlr/antlr-4.0-complete.jar:. org.antlr.v4.runtime.misc.TestRig'


grun Hello r -tokens

I could not find which EOF key to press on Windows (it's CTRL-D in Linux).



If more people knew how to write a grammar and a parser, we probably would not be wasting so much of our life manually sorting horrendous Maven pom.xml files, or hacking HTML pages embedded with all sort of obscure hocus-pocus additions, or even typing unreadable GIT commands to undo a commit.

But we don't want to be monkeys, we want to learn the fundamentals of our profession : elaborate languages to explain, in a clear concise and unambiguous way, what we expect from a computing machine.



Troubleshooting:


If you get
java.lang.NullPointerException
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:311)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.antlr.v4.runtime.misc.TestRig.process(TestRig.java:157)
at org.antlr.v4.runtime.misc.TestRig.main(TestRig.java:142)

check this:

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/sun/misc/Launcher.java?av=f

public Class<?>  [More ...] loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
int i = name.lastIndexOf('.');
if (i != -1) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPackageAccess(name.substring(0, i));
}
}

and this http://grepcode.com/file/repo1.maven.org/maven2/org.antlr/antlr4/4.0/org/antlr/v4/runtime/misc/TestRig.java?av=f

try {
lexerClass = cl.loadClass(lexerName).asSubclass(Lexer.class);
}

At this point I am pretty hopeless.... just ignore this issue, when you run grun with parameters, it works.

See https://github.com/antlr/antlr4/issues/174


Friday, April 6, 2018

WebLogic on Kubernetes

https://blogs.oracle.com/weblogicserver/weblogic-server-certification-on-kubernetes

https://github.com/oracle/docker-images/tree/master/OracleWebLogic/dockerfiles/12.2.1.3

sample Dockerfile https://github.com/oracle/docker-images/blob/master/OracleWebLogic/samples/wls-k8s-domain/Dockerfile

WebLogic Dockerfiles are at https://github.com/oracle/docker-images/tree/master/OracleWebLogic



Katacoda docker interactive tutorial

Katacoda is the best thing I have seen this year. IT teachers and IT books are made obsolete by this tool.

https://www.katacoda.com/courses/docker/deploying-first-container

docker search redis

docker run -d redis

docker ps

docker inspect 654e238d3bef
docker logs 654e238d3bef

docker run -d --name redisHostPort -p 6379:6379 redis:latest

docker run -d --name redisDynamic -p 6379 redis:latest

docker port redisDynamic 6379

docker run -d --name redisMapped -v /opt/docker/data/redis:/data redis

docker run -d ubuntu ps
docker exec ubuntu bash

Dockerfile
FROM nginx:alpine
COPY . /usr/share/nginx/html

docker build -t webserver-image:v1 .

docker images

docker run -d -p 80:80 webserver-image:v1

curl docker
cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
127.0.0.1       registry.test.training.katacoda.com
172.17.0.51     host01 751a165ea438 st_4yzuip_d2d
172.17.0.51     docker 751a165ea438 st_4yzuip_d2d
172.17.0.36     e1c00230b89e

to create data container:
docker create -v /config --name dataContainer busybox

docker cp config.conf dataContainer:/config/
docker run --volumes-from dataContainer ubuntu ls /config

to move the data container to another machine:
docker export dataContainer > dataContainer.tar
docker import dataContainer.tar



Networks

docker network create backend-network
docker run -d --name=redis --net=backend-network redis
docker run --net=backend-network alpine env
docker run --net=backend-network alpine cat /etc/resolv.conf
nameserver 127.0.0.11
options ndots:0

docker run --net=backend-network alpine ping -c1 redis
docker network create frontend-network
docker network connect frontend-network redis
docker run -d -p 3000:3000 --net=frontend-network katacoda/redis-node-docker-example
curl docker:3000

docker network create frontend-network2
docker network connect --alias db frontend-network2 redis
docker run --net=frontend-network2 alpine ping -c1 db










The Kubernetes Book by Nigel Poulton

I have learned much more from "Kubernetes Webinar Series" freely available on youtube. Unless you are a really total beginner, you have already heard/read most of the stuff in this book.

https://en.wikipedia.org/wiki/Kubernetes


https://labs.play-with-k8s.com/

on node1:

kubeadm init --apiserver-advertise-address $(hostname -i)
kubectl version | base64 |tr -d '\n'
kubectl version
kubectl apply -n kube-system -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 |tr -d'\n')"
kubectl apply -f https://k8s.io/docs/user-guide//nginx-app.yaml
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
whoami
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
kubectl
id
cd
cd .kube
ls -ltra
vi config
kubectl get nodes

on node2:

hostname
kubeadm join --token 523042.dd2ec91db1bf45d0 192.168.112.2:6443 --discovery-token-ca-cert-hash sha256:c48cc070ad8759a57293a41598c197a48faba5deb3f1475fd127713b4fc32aeb



Eclipse generate JPA entities from DB

Unfortunately there doesn't seem to exist a tool to generate JPA Entities directly from SQL. Weird!
So you have to start by populating a real schema.

Create a Java project

Configure "Targeted Runtimes" with "Wildfly 11 Runtime"

Configure Project, Facets, and select JPA (ignore the "further configuration available")

Right-click on Project, you should see "JPA Tools", "Generate Entities from tables"



When I was young I was thinking of 2017 as the age of teletransportation and instant cure for all diseases. Instead it's the age of wasting hours for a Maven configuration. I bet the Cro-Magnon were more technologically savvy than the Maven folks.




Kubernetes up and running


https://github.com/kubernetes-up-and-running/examples




more Docker in Action

docker run -d --volume /var/lib/cassandra/data --name cass-shared alpine echo Data Container

docker run -d --volumes-from cass-shared --name cass1 cassandra:2.2

docker run -it --rm --link cass1:cass cassandra:2.2 cqlsh cass

select * from system.schema_keyspaces where keyspace_name = 'docker_hello_world';

create keyspace docker_hello_world with replication = { 'class' : 'SimpleStrategy', 'replication_factor': 1 };

select * from system.schema_keyspaces where keyspace_name = 'docker_hello_world';

quit

docker stop cass1
docker rm -vf cass1

docker run -d --volumes-from cass-shared --name cass2 cassandra:2.2
docker run -it --rm --link cass2:cass cassandra:2.2 cqlsh cass
select * from system.schema_keyspaces where keyspace_name = 'docker_hello_world';

quit

docker rm -vf cass2 cass-shared

#bind-mount volumes point to a space on the host 


cd 
mkdir example-docs
echo "ciao" > example-docs/index.html

docker run -d --name bmweb -v ~/example-docs:/usr/local/app 80:80 httpd:latest

#enter localhost:80 in your browser, you should see "ciao"

#create a file on the guest system
docker run --rm -v ~/example-docs:/testspace alpine /bin/sh -c 'echo test > /testspace/test'

#this will fail - read only
docker run --rm -v ~/example-docs:/testspace:ro alpine /bin/sh -c 'echo test2 > /testspace/test'

#check how the volume is mounted
docker run --rm -v ~/example-docs/absent:/absent alpine:latest /bin/sh -c 'mount | grep absent'







Openshift Online getting started

Create yourself an Openshift Online account (account creation seems to me a bit buggish)

https://docs.openshift.com/online/getting_started/basic_walkthrough.html

I follow the instructions and create my first mongodb / nodejs Openshift project


I download the CLI https://console.starter-ca-central-1.openshift.com/console/command-line

oc login https://api.starter-ca-central-1.openshift.com --token=4zlxeYZvlO9FdfvcBEEVZpMca-JA5UftBzShxdkGITI

oc project vernetto-example


.\oc.exe status
In project vernetto-example on server https://api.starter-ca-central-1.openshift.com:443

svc/mongodb - 172.30.171.215:27017
  dc/mongodb deploys openshift/mongodb:3.2
    deployment #1 deployed 15 minutes ago - 1 pod

http://nodejs-mongo-persistent-vernetto-example.193b.starter-ca-central-1.openshiftapps.com (svc/nodejs-mongo-persistent)
  dc/nodejs-mongo-persistent deploys istag/nodejs-mongo-persistent:latest <-
    bc/nodejs-mongo-persistent source builds https://github.com/vernetto/nodejs-ex.git on openshift/nodejs:6
    deployment #1 deployed 13 minutes ago - 1 pod

View details with 'oc describe /' or list everything with 'oc get all'.



.\oc.exe config view
apiVersion: v1
clusters:
- cluster:
    api-version: v1
    server: https://api.starter-ca-central-1.openshift.com:443
  name: api-starter-ca-central-1-openshift-com:443
contexts:
- context:
    cluster: api-starter-ca-central-1-openshift-com:443
    namespace: vernetto-example
    user: publicpierre/api-starter-ca-central-1-openshift-com:443
  name: vernetto-example/api-starter-ca-central-1-openshift-com:443/publicpierre
current-context: vernetto-example/api-starter-ca-central-1-openshift-com:443/publicpierre
kind: Config
preferences: {}
users:
- name: publicpierre/api-starter-ca-central-1-openshift-com:443
  user:
    token: 4zlxeYZvlO9FdbvcBEEVZpMca-JA5UftBzShxdkGVTI



.\oc.exe project
Using project "vernetto-example" on server "https://api.starter-ca-central-1.openshift.com:443".




.\oc.exe get svc
NAME                      CLUSTER-IP       EXTERNAL-IP   PORT(S)     AGE
mongodb                   172.30.171.215           27017/TCP   3h
nodejs-mongo-persistent   172.30.187.89            8080/TCP    3h




The file C:\Users\publi\.kube\config contains the authentication info:

apiVersion: v1
clusters:
- cluster:
    api-version: v1
    server: https://api.starter-ca-central-1.openshift.com:443
  name: api-starter-ca-central-1-openshift-com:443
contexts:
- context:
    cluster: api-starter-ca-central-1-openshift-com:443
    namespace: vernetto-example
    user: publicpierre/api-starter-ca-central-1-openshift-com:443
  name: vernetto-example/api-starter-ca-central-1-openshift-com:443/publicpierre
current-context: vernetto-example/api-starter-ca-central-1-openshift-com:443/publicpierre
kind: Config
preferences: {}
users:
- name: publicpierre/api-starter-ca-central-1-openshift-com:443
  user:
    token: 4zlxeYZvlO9FdbacBEEVqpMca-JA5UftBfShxdkGVTI


with the 4 sections clusters, contexts, current-context, users


.\oc.exe get quota
NAME                          AGE
compute-resources             5h
compute-resources-timebound   5h
object-counts                 5h


.\oc.exe describe quota compute-resources
Name:           compute-resources
Namespace:      vernetto-example
Scopes:         NotTerminating
 * Matches all pods that do not have an active deadline. 
These pods usually include long running pods whose container command is not expected to terminate.
Resource        Used    Hard
--------        ----    ----
limits.cpu      2       2
limits.memory   1Gi     1Gi


.\oc.exe export services
apiVersion: v1
items:
- apiVersion: v1
  kind: Service
  metadata:
    annotations:
      description: Exposes the database server
    creationTimestamp: null
    labels:
      app: nodejs-mongo-persistent
      template: nodejs-mongo-persistent
    name: mongodb
  spec:
    ports:
    - name: mongodb
      port: 27017
      protocol: TCP
      targetPort: 27017
    selector:
      name: mongodb
    sessionAffinity: None
    type: ClusterIP
  status:
    loadBalancer: {}
- apiVersion: v1
  kind: Service
  metadata:
    annotations:
      description: Exposes and load balances the application pods
      service.alpha.openshift.io/dependencies: '[{"name": "mongodb", "kind": "Service"}]'
    creationTimestamp: null
    labels:
      app: nodejs-mongo-persistent
      template: nodejs-mongo-persistent
    name: nodejs-mongo-persistent
  spec:
    ports:
    - name: web
      port: 8080
      protocol: TCP
      targetPort: 8080
    selector:
      name: nodejs-mongo-persistent
    sessionAffinity: None
    type: ClusterIP
  status:
    loadBalancer: {}
kind: List
metadata: {}



to manually start a build:

oc start-build nodejs-mongo-persistent -n vernetto-example






Xml Parsing, tools, strategies and alternatives

JAXB



If you have an xsd, you can generate the @javax.xml.bind.annotation.XmlRootElement annotated Java POJOs with xjc:
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/xjc.html
example:
cd D:\pierre\wildfly-11.0.0.CR1\docs\schema

xjc .\wildfly-config_5_0.xsd -d D:\pierre\workspaceneon\PVXmlParser\src\


Here an example to PARSE an xml file https://www.javacodegeeks.com/2013/02/jaxb-tutorial-getting-started.html

Here the https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/Unmarshaller.html

To generate an XSD from existing XML, try http://www.thaiopensource.com/relaxng/trang-manual.html (a bit old tool...)

package org.pierre.jbossconf;

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import jboss.domain._5.Server;


public class XmlParser {
 public static void main(String[] args) throws JAXBException {
  JAXBContext jaxbContext = JAXBContext.newInstance(Server.class);
  Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
  File standaloneXmlFile = new File("D:\\pierre\\wildfly-11.0.0.CR1\\standalone\\configuration\\standalone.xml");
  Server server = (Server)jaxbUnmarshaller.unmarshal(standaloneXmlFile);
  server.getProfile().getAny().forEach((item) -> {System.out.println(item);}); 
 }

}



in my case, parsing fails because of missing tokes substitution "Not a number: ${jboss.socket.binding.port-offset:0}"

these variables are present in thee standalone.xml file:
jboss.deployment.scanner.rollback.on.failure
prop.remoting-connector.read.timeout
jboss.home.dir
jboss.bind.address
jboss.bind.address.management
jboss.bind.address
jboss.socket.binding.port-offset
jboss.management.http.port
jboss.management.https.port
jboss.ajp.port
jboss.http.port
jboss.https.port


Spring core tutorial

Although a bit outdated, it goes over the main points https://www.tutorialspoint.com/spring/

I have put the code of each step in https://github.com/vernetto/springdemo , instructions in the readme.md, a separate tag for each step. The class to run is MainApp.



Spring testing

spring-test

https://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html

spring-boot-test

https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html

@ContextConfiguration(locations = "/test-db-context.xml")

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.pierre.sourcing.dao, com.pierre.xcoll.dao" />

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@pippo:1521:PLUTO" />
        <property name="username" value="pippouser" />
        <property name="password" value="pippopassword" />
    </bean>

    <bean id="transManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
        <property name="dataSource" ref="dataSource" />
    </bean>

    <context:component-scan base-package="com.pierre.sourcing.dao" />
</beans>



Important annotations

org.springframework.test.annotation.Rollback; indicates whether the transaction for a transactional test method should be rolled back after the test method has completed.

org.springframework.transaction.annotation.Transactional

org.springframework.test.context.ContextConfiguration @ContextConfiguration("/test-config.xml") declares the application context resource locations or the annotated classes that will be used to load the context.

org.springframework.test.context.jdbc.Sql at class level, like in @Sql(scripts = "/preparation-sqls/cleanup-test-data.sql") , to run SQL BEFORE the test execution

org.springframework.test.context.junit4.SpringRunner (@RunWith(SpringRunner.class) )

org.springframework.beans.factory.annotation.Autowired



Docker resource control

systemd-cgls
systemd-cgtop

ls -ltr /sys/fs/cgroup/

https://goldmann.pl/blog/2014/09/11/resource-management-in-docker/


mkdir stress
cd stress/

cat <<EOT >> Dockerfile
FROM fedora:latest
RUN yum -y install stress && yum clean all
ENTRYPOINT ["stress"]
EOT

docker build . -t stress
docker run -d stress --cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 30s
systemd-cgtop


To display the scope of a container:

docker ps --no-trunc
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c82c5d0e0a0dac72ce935fd10c49bb0c6f680f009cdce20995b1c731d9698d80 ubuntu "/usr/bin/top -b" 38 hours ago Up 37 hours topdemo

systemctl show docker-c82c5d0e0a0dac72ce935fd10c49bb0c6f680f009cdce20995b1c731d9698d80.scope


TimeoutStopUSec=1min 30s
Result=success
MemoryCurrent=18446744073709551615
TasksCurrent=18446744073709551615
Delegate=no
CPUAccounting=no
CPUShares=18446744073709551615
StartupCPUShares=18446744073709551615
CPUQuotaPerSecUSec=infinity
BlockIOAccounting=no
BlockIOWeight=18446744073709551615
StartupBlockIOWeight=18446744073709551615
MemoryAccounting=no
MemoryLimit=18446744073709551615
DevicePolicy=auto
TasksAccounting=no
TasksMax=18446744073709551615
KillMode=control-group
KillSignal=15
SendSIGKILL=yes
SendSIGHUP=no
Id=docker-c82c5d0e0a0dac72ce935fd10c49bb0c6f680f009cdce20995b1c731d9698d80.scope
Names=docker-c82c5d0e0a0dac72ce935fd10c49bb0c6f680f009cdce20995b1c731d9698d80.scope
Description=docker-c82c5d0e0a0dac72ce935fd10c49bb0c6f680f009cdce20995b1c731d9698d80.scope
LoadState=not-found
ActiveState=inactive
SubState=dead
InactiveExitTimestampMonotonic=0
ActiveEnterTimestampMonotonic=0
ActiveExitTimestampMonotonic=0
InactiveEnterTimestampMonotonic=0
CanStart=yes
CanStop=yes
CanReload=no
CanIsolate=no
StopWhenUnneeded=no
RefuseManualStart=no
RefuseManualStop=no
AllowIsolate=no
DefaultDependencies=yes
OnFailureJobMode=replace
IgnoreOnIsolate=yes
IgnoreOnSnapshot=yes
NeedDaemonReload=no
JobTimeoutUSec=0
JobTimeoutAction=none
ConditionResult=no
AssertResult=no
ConditionTimestampMonotonic=0
AssertTimestampMonotonic=0
LoadError=org.freedesktop.DBus.Error.FileNotFound "No such file or directory"
Transient=no


cat /proc/meminfo

cat /proc/vmstat


#remove all containers with stress image
docker ps -a | awk '{ print $1,$2 }' | grep stress | awk '{print $1 }' | xargs -I {} docker rm {}
#or even better
docker ps -a -q --filter=ancestor=stress | xargs -I {} docker rm {}

dockerd --iptables=false



References

https://www.javacodegeeks.com/minibook/docker-containerization-cookbook

https://fralef.me/docker-and-iptables.html




Thursday, April 5, 2018

primefaces cookbook on wildfly

The book is covering in depth many examples available on the official PF showcase. Don't expect advanced programming techniques, it's purely about implement not-so-common use cases in PF


sample code is here https://github.com/ova2/primefaces-cookbook

git clone git://github.com/ova2/primefaces-cookbook.git
cd primefaces-cookbook
mvn install

copy $MAVEN_REPO/org/primefaces/cookbook/showcase/2.0.0/showcase-2.0.0.war to /opt/wildfly12/standalone/deployments

http://localhost:8180/pf-cookbook/ (or http://localhost:8080/pf-cookbook/ )



Friday, March 30, 2018

Wildfly file upload and download with Primefaces

Sample application available here https://github.com/vernetto/pffile

https://www.primefaces.org/docs/api/6.2/org/primefaces/model/UploadedFile.html


https://stackoverflow.com/a/8880083/651288 read BalusC comments


in pom.xml add this:
<dependency>
 <groupId>commons-fileupload</groupId>
 <artifactId>commons-fileupload</artifactId>
 <version>1.3</version>
</dependency>
<dependency>
 <groupId>commons-io</groupId>
 <artifactId>commons-io</artifactId>
 <version>2.2</version>
</dependency>

in web.xml add this:

<filter>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
</filter-mapping>



If you get this error:

io.undertow.server.RequestTooBigException: UT000020: Connection terminated as request was larger than 10485760

change the max-post-size parameter:

Configuration: Subsystems Subsystem: Web/HTTP - Undertow Settings: HTTP


<subsystem xmlns="urn:jboss:domain:undertow:5.0">
<buffer-cache name="default"/>
<server name="default-server">
<http-listener name="default" socket-binding="http" max-post-size="1000000000" redirect-socket="https" enable-http2="true"/>


Missing features: enable streaming for large files, show progress bar




Wednesday, March 28, 2018

Nexus 3 as a Docker GROUP around a proxy and 2 hosted repos

We want to provide this setup:

dockergroup repository, "covering" a dockerproxy repo (proxy to docker hub) and 2 hosted repos

Each repo will have its own http port!

1) create these blob stores dockergroup, dockerproxy, dockerhosted1, dockerhosted2 (it's better to have a separate blob store per repo.... beware, the dockergroup blobstore will always stay empty, all the actual store is done in the proxy and hosted repos)

2) create repo dockerproxy,format docker, HTTP port 8084, HTTPS 8484, Enable Docker V1 API, remote storage https://registry-1.docker.io , Docker Index "User Docker Hub"

3) create repo dockerhosted1 (blob dockerhosted1, port http 8082 https 8482) and dockerhosted2 (blob dockerhosted2 port http 8083 https 8483)

4) create repo dockergroup (blob dockergroup, http 8085 https 8485) with members dockerproxy, dockerhosted1, dockerhosted2


Now when you want to PULL images, you should login into dockergroup (8085) or into dockerproxy (8084).
To PUSH images to your HOSTED, you have to login directly into the dockerhosted1 (8082) or dockerhosted2 (8083). PUSHing to the dockergroup will not work, he has no means to ROUTE the image to dockerhosted1 or dockerhosted2 based on some rule.... This is quite a pity indeed, it would be nice if a group had some routing facilities.



Nexus repository administration automation

On the whole, it doesn't seem Sonatype is taking it very seriously. As usual, documentation is scattered everywhere, some automation tools exist but who knows if they are even supported. I think most users simply do everything manually in the Nexus web console :o((((

http://localhost:8081/swagger-ui was working in 3.5 , now in 3.9 you must enter http://localhost:8081/swagger-ui/#/ (see https://issues.sonatype.org/browse/NEXUS-13948 )

If you want to automate the creation of repositories, swagger exposes you only "list repos" http://localhost:8081/swagger-ui/#!/repositories/getRepositories

Interesting articles :

https://dzone.com/articles/automated-setup-of-a-repository-manager

https://help.sonatype.com/repomanager3/rest-and-integration-api

Generic nexus-cli to manage Nexus in Groovy scripts https://github.com/RiotGamesMinions/nexus_cli

Interesting nexus-cli to manage Docker images in Nexus https://github.com/mlabouardy/nexus-cli



Sunday, March 25, 2018

h2 remote

./h2.sh -tcpAllowOthers -webAllowOthers


Web Console server running at http://localhost:8082 (others can connect)
Failed to start a browser to open the URL http://localhost:8082: Browser detection failed and system property h2.browser not set
TCP server running at tcp://localhost:9092 (others can connect)
PG server running at pg://localhost:5435 (only local connections)


At this point you can connect remotely to the console (even if it says "localhost") and you can specify a remote tcp url in your datasource:

jdbc:h2:tcp://YOURIP:9092/~/YOURDB;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE

When using h2, don't forget to use

<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>

in your persistence.xml
(see http://www.mastertheboss.com/jboss-server/jboss-datasource/h2-database-tutorial )


VirtualBox Centos7 high CPU for VBoxClient process

The issue is reported here https://forums.virtualbox.org/viewtopic.php?f=6&t=83507

Occasionally the VBoxClient eats 100% CPU forever - which affects greatly also the host performance - and the only way to stop it is to shut down the VM.

I have: disabled drag-and-drop, disabled shared folder and simply "kill -9" the process - this seems to cause no side effects.



Installing Docker Java and Wildfly on DigitalOcean Centos7 droplet


https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-centos-7

https://devops.profitbricks.com/tutorials/how-to-install-and-configure-wildfly-application-server-on-centos-7/


Login as root

yum check-update
curl -fsSL https://get.docker.com/ | sh
sudo usermod -aG docker centos
sudo systemctl start docker
sudo systemctl status docker
sudo systemctl enable docker
#make sure that user centos exists
sudo su - centos // then exit
#download and copy here the jdk
tar -xzvf jdk-8u161-linux-x64.tar.gz -C /opt/
alternatives --install /usr/bin/java java /opt/jdk1.8.0_161/bin/java 2
alternatives --config java
alternatives --install /usr/bin/jar jar /opt/jdk1.8.0_161/bin/jar 2
alternatives --install /usr/bin/javac javac /opt/jdk1.8.0_161/bin/javac 2
alternatives --set jar /opt/jdk1.8.0_161/bin/jar
alternatives --set javac /opt/jdk1.8.0_161/bin/javac
java -version

vi /etc/profile.d/java.sh

if ! echo ${PATH} | grep -q /opt/jdk1.8.0_161/bin ; then
   export PATH=/opt/jdk1.8.0_161/bin:${PATH}
fi
if ! echo ${PATH} | grep -q /opt/jdk1.8.0_161/jre/bin ; then
   export PATH=/opt/jdk1.8.0_161/jre/bin:${PATH}
fi
export JAVA_HOME=/opt/jdk1.8.0_161
export JRE_HOME=/opt/jdk1.8.0_161/jre
export CLASSPATH=.:/opt/jdk1.8.0_161/lib/tools.jar:/opt/jdk1.8.0_161/jre/lib/rt.jar

vi /etc/profile.d/java.csh

if ( "${path}" !~ */opt/jdk1.8.0_161/bin* ) then
   set path = ( /opt/jdk1.8.0_161/bin $path )
endif
if ( "${path}" !~ */opt/jdk1.8.0_161/jre/bin* ) then
    set path = ( /opt/jdk1.8.0_161/jre/bin $path )
endif
setenv JAVA_HOME /opt/jdk1.8.0_161
setenv JRE_HOME /opt/jdk1.8.0_161/jre
setenv CLASSPATH .:/opt/jdk1.8.0_161/lib/tools.jar:/opt/jdk1.8.0_161/jre/lib/rt.jar



chmod 755 /etc/profile.d/java.sh
chmod 755 /etc/profile.d/java.csh
curl -O http://download.jboss.org/wildfly/10.1.0.Final/wildfly-10.1.0.Final.zip
yum install unzip
unzip wildfly-10.1.0.Final.zip -d /opt/
#set JBOSS_HOME and JAVA_HOME
vi /opt/wildfly-10.1.0.Final/bin/standalone.conf
#set JBOSS_HOME and JAVA_HOME
vi /etc/profile
#set the right IP address
vi /opt/wildfly-10.1.0.Final/standalone/configuration/standalone.xml
cd /opt/wildfly-10.1.0.Final/bin/
./add-user.sh

chown -R centos:centos /opt/wildfly-10.1.0.Final/

su - centos
#start wildfly
cd /opt/wildfly-10.1.0.Final/bin
./standalone.sh



Create these entries in your /home/centos/.bash_profile

export WF_BIN=/opt/wildfly-10.1.0.Final/bin/
export WF_DEP=/opt/wildfly-10.1.0.Final/standalone/deployments/
export WF_TMP=/opt/wildfly-10.1.0.Final/standalone/tmp/
export WF_LOG=/opt/wildfly-10.1.0.Final/standalone/log/
alias STARTWF="cd $WF_BIN; nohup ./standalone.sh 2>&1 > standalone.log &"








Saturday, March 24, 2018

Maven/Eclipse Horror Show

I have updated recently my Maven binaries, of course I forgot to change The "User Settings" property in Eclipse to point to the new location of the settings.xml.

Of course Eclipse silently fails to report the issue (unless you go and open the Maven tab in Preferences)

And all of a sudden nothing works and when I open my pom.xml I get this:

Project build error: Non-resolvable parent POM for org.wildfly.quickstarts:quickstart-parent:13.0.0-SNAPSHOT: Could not transfer artifact org.jboss:jboss-parent:pom:25 from/to jboss-enterprise-maven-repository (https://maven.repository.redhat.com/ga/): NullPointerException and 'parent.relativePath' points at no local POM


Working with Maven and Eclipse I feel young again.... it feels like the 1985 - actually my Pascal compiler on Apple II was far more sophisticated that these modern products.




Thursday, March 22, 2018

WinSCP plugin for Far Manager no longer supported

I love Far Manager for its very quick, keyboard driven interface. It has been my favorite workhorse for at least 15 years.

Now unfortunately I can no longer use it to connect to a Centos VB with WinSCP plugin, I keep getting:

"expected key exchange group packet from server"

I discovered that now it's replaced by NetBox plugin:

https://github.com/michaellukashov/Far-NetBox/releases/download/v2.4.3.512/FarNetBox-2.4.3_Far3_x64.7z


Just do F11 (Plugin) , Netbox and you connect on port 2222 (forwarding of port 22 in VirtualBox) with centos/centos

Excellent!


Using Nexus 3 as a Docker registry Proxy

http://books.sonatype.com/nexus-book/3.0/reference/docker.html#docker-proxy


If you are behind a firewall, you need to open :

https://registry-1.docker.io
https://index.docker.io/


As explained here https://hub.docker.com/r/sonatype/nexus3/ I run

docker run -d -p 8081:8081 -p 8082:8082 --name nexus sonatype/nexus3

You can open http://localhost:8081/ and login as admin/admin123

At this point, Docker is still not setup in Nexus:

In Nexus console, create a new Docker Proxy repo name "dockerproxy" , URL "https://registry-1.docker.io", Docker index "use docker hub". Also, "enable docker v1 api" checkbox. Choose port HTTP 8082 (it will accept logins only on port 8082, not on 8081!)

You should be able to see its (empty for now) index here http://localhost:8081/service/rest/repository/browse/dockerproxy/

To configure your docker engine to communicate to the registry:

sudo vi /etc/docker/daemon.json

Add this line:

{"insecure-registries" : [ "localhost:8081", "localhost:8082" ]}

Restart Docker Daemon:

sudo systemctl daemon-reload

sudo systemctl restart docker



WRONG:
docker login localhost:8081

Username: admin
Password:
Error response from daemon: login attempt to http://localhost:8081/v2/ failed with status: 404 Not Found


RIGHT:
docker login localhost:8082

Username: admin
Password:
Login Succeeded







Tag and push your first image:

#check your local images

docker images

#log into nexus registry

docker --debug=true login localhost:8082 -u admin -p admin123

sudo docker run localhost:8082/hello-world


You can also create a hosted Docker repository, better if you create a user pippo/pippo and give it access to the Repository,

then "docker login localhost:8082 -u pippo -p pippo" and to push something
docker tag <image>:<tag> localhost:8082/<image>:<tag> #example: docker tag service:1.2 localhost:8082/service:1.2

#push your tagged image to nexus
docker push localhost:8082/service:1.2

Troubleshooting:

Check what happens in nexus, in request.log (in /nexus-data/log) I see all HTTP requests issued by docker:

172.17.0.1 - - [21/Mar/2018:10:28:19 +0000] "GET /v2/ HTTP/1.1" 404 1783 8 "docker/18.03.0-ce-rc4 go/go1.9.4 git-commit/fbedb97 kernel/3.10.0-693.21.1.el7.x86_64 os/linux arch/amd64 UpstreamClient(Docker-Client/18.03.0-ce-rc4 \(linux\))"




Wednesday, March 21, 2018

Downgrade from Docker 18 to Docker 1.12

sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine
yum list installed | grep docker

THIS IS NOT WORKING (it installs Docker 18 !!!)

sudo yum -y update
sudo yum -y install yum-utils
sudo yum-config-manager --add-repo https://yum.dockerproject.org/repo/main/centos/7
sudo yum -y update
# yum search --showduplicates docker-engine
sudo yum -y --nogpgcheck install docker-engine-1.12.6-1.el7.centos.x86_64
sudo systemctl enable docker
sudo systemctl start docker
yum list installed | grep docker
docker version



THIS IS WORKING
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine
yum list installed | grep docker
sudo yum install -y libtool-ltdl libseccomp
mkdir docker
cd docker
wget https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-1.12.6-1.el7.centos.x86_64.rpm https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-selinux-1.12.6-1.el7.centos.noarch.rpm
wget https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-1.12.6-1.el7.centos.x86_64.rpm \
sudo rpm -ivh docker-engine-1.12.6-1.el7.centos.x86_64.rpm docker-engine-selinux-1.12.6-1.el7.centos.noarch.rpm
yum list installed | grep docker
sudo systemctl start docker
sudo systemctl enable docker
docker version




Upgrade docker to version 18 on Centos

For stability love I was sticking to docker 1.12....
Several new features are interesting, so I am upgrading...
This link https://docs.docker.com/install/linux/docker-ce/centos/#set-up-the-repository
is really useful

This is what I have done:

docker version
sudo yum remove docker docker-common docker-selinux docker-engine
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum-config-manager --enable docker-ce-edge
sudo yum-config-manager --enable docker-ce-test
sudo yum install docker-ce
docker version




Client:
Version: 18.03.0-ce-rc4
API version: 1.37
Go version: go1.9.4
Git commit: fbedb97
Built: Thu Mar 15 07:40:24 2018
OS/Arch: linux/amd64
Experimental: false
Orchestrator: swarm
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?



oops I forgot to start and enable:

sudo systemctl start docker
sudo systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.


docker version

Client:
Version: 18.03.0-ce-rc4
API version: 1.37
Go version: go1.9.4
Git commit: fbedb97
Built: Thu Mar 15 07:40:24 2018
OS/Arch: linux/amd64
Experimental: false
Orchestrator: swarm

Server:
Engine:
Version: 18.03.0-ce-rc4
API version: 1.37 (minimum version 1.12)
Go version: go1.9.4
Git commit: fbedb97
Built: Thu Mar 15 07:44:03 2018
OS/Arch: linux/amd64
Experimental: false



sudo systemctl status docker

[sudo] password for centos:
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2018-03-21 09:58:07 CET; 1h 25min ago
Docs: https://docs.docker.com
Main PID: 19616 (dockerd)
Tasks: 47
Memory: 55.7M
CGroup: /system.slice/docker.service
├─19616 /usr/bin/dockerd
├─19631 docker-containerd --config /var/run/docker/containerd/containerd.toml
├─20235 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8081 -container-ip 172.17.0.2 -container-port 8081
└─20241 docker-containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/d510b3bfdff1a6ff247d08f101c463fa2c496ea52ff6f822c5cc8736b8d04b81 -addre...

Mar 21 09:58:04 localhost.localdomain dockerd[19616]: time="2018-03-21T09:58:04.569448393+01:00" level=info msg="[graphdriver] using prior storage driver: devicemapper"
Mar 21 09:58:05 localhost.localdomain dockerd[19616]: time="2018-03-21T09:58:05.554399630+01:00" level=info msg="Graph migration to content-addressability took 0.00 seconds"
Mar 21 09:58:05 localhost.localdomain dockerd[19616]: time="2018-03-21T09:58:05.559942092+01:00" level=info msg="Loading containers: start."
Mar 21 09:58:06 localhost.localdomain dockerd[19616]: time="2018-03-21T09:58:06.971793300+01:00" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon opti...d IP address"
Mar 21 09:58:07 localhost.localdomain dockerd[19616]: time="2018-03-21T09:58:07.568225034+01:00" level=info msg="Loading containers: done."
Mar 21 09:58:07 localhost.localdomain dockerd[19616]: time="2018-03-21T09:58:07.634962555+01:00" level=info msg="Docker daemon" commit=fbedb97 graphdriver(s)=devicemapper version=18.03.0-ce-rc4
Mar 21 09:58:07 localhost.localdomain dockerd[19616]: time="2018-03-21T09:58:07.635202601+01:00" level=info msg="Daemon has completed initialization"
Mar 21 09:58:07 localhost.localdomain dockerd[19616]: time="2018-03-21T09:58:07.682479847+01:00" level=info msg="API listen on /var/run/docker.sock"
Mar 21 09:58:07 localhost.localdomain systemd[1]: Started Docker Application Container Engine.
Mar 21 10:04:44 localhost.localdomain dockerd[19616]: time="2018-03-21T10:04:44+01:00" level=info msg="shim docker-containerd-shim started" address="/containerd-shim/moby/d510b3bfdff1a6ff247d08f1...ks" pid=20241
Hint: Some lines were ellipsized, use -l to show in full.






Friday, March 16, 2018

Jenkins pipelines

https://www.youtube.com/watch?v=TsWkZLLU-s4&t=1188s


https://github.com/abayer/dec-jam-declarative-demos

http://www.mdoninger.de/2011/11/07/write-groovy-scripts-for-jenkins-with-code-completion.html Jenkins code completion in Eclipse (doh! Who would have thought of using a IDE to write code! The new frontier is write pipeline code in a browser on a github tab.... next they will ask you to write pcode in hex format... then we will eat bananas on trees again)


picture 1: Jenkins developers discussing the use of Notepad to improve coding experience



picture 2: Jenkins developers celebrate their first successful Scripted pipeline


picture 3: Jenkins developers discover IDE

Thursday, March 15, 2018

/var/run/docker.sock

ls -ltra /var/run/docker.sock
srw-rw----. 1 root docker 0 Feb 12 15:49 /var/run/docker.sock



https://www.gnu.org/software/coreutils/manual/html_node/What-information-is-listed.html#What-information-is-listed "s" stands for Unix socket

Communication between a Docker container and Docker daemon can happen via this socket (see Portainer and "docker in docker"


https://medium.com/lucjuggery/about-var-run-docker-sock-3bfd276e12fd
excellent explanation of the /var/run/docker.sock


This REST call via /var/run/docker.sock will create a cointainer:

docker pull nginx:latest
curl -H "Content-Type: application/json" -X POST --unix-socket /var/run/docker.sock -d '{"Image":"nginx"}' http://localhost/containers/create

amazing!


This PRICELESS command, run on the host, can trace all the events handled by the docker daemon:

curl --unix-socket /var/run/docker.sock http://localhost/events



Jenkins console

interesting presentation (skip first 9 minutes)



Scripts:

println "I hacked you"
new File('/etc/passwd').text


println "${Jenkins.instance.root}"

"ls -ltr /".execute().text

Jenkins.getInstance().metaClass.methods*.name.sort().unique()


on Jenkins CLI https://wiki.jenkins.io/display/JENKINS/Jenkins+CLI

the scripts by Sam https://github.com/samrocketman/jenkins-script-console-scripts

https://github.com/jenkinsci/jenkins-scripts


http://groovy-lang.org/learn.html

https://wiki.jenkins.io/display/JENKINS/Jenkins+Script+Console

Sunday, March 11, 2018

dind docker in docker , permission denied on /var/run/docker.sock



Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.33/version: dial unix /var/run/docker.sock: connect: permission denied

ls -alh /var/run/docker.sock
srw-rw----. 1 root docker 0 Mar 11 15:45 /var/run/docker.sock


doing "chmod 777 /var/run/docker.sock" doesn't help


on the host:

docker version
Client:
Version: 1.12.6
API version: 1.24


in the container:

docker version
Client:
Version: 17.10.0-ce
API version: 1.33



The problem went away by installing on the host the latest docker version as per https://docs.docker.com/install/linux/docker-ce/centos/#install-using-the-convenience-script

Thursday, March 1, 2018

SELinux

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/security-enhanced_linux/chap-security-enhanced_linux-introduction#sect-Security-Enhanced_Linux-Introduction-Benefits_of_running_SELinux


Priceless wiki https://wiki.centos.org/HowTos/SELinux

#disable DAC (must be root), will only log rule violations
setenforce 0
#enable it
setenforce 1
#check
getenforce

#display info
sestatus
cat /etc/selinux/config

DAC and MAC (discretionary and mandatory access control). First DAC is applied, then MAC (if DAC succeeds).
#list user, role, type, level
ls -Z myfile


Access Vector Cache (AVC)

#view SELinux-Linux user mappings
semanage login -l

#view the SELinux context for processes
ps -eZ


#view SELinux context associated to your user
id -Z

#label a file with a type (transient)
chcon -t

#permanent relabeling of file
semanage

#restore default context for process
restorecon


In Apache, if you get this:

[Tue Feb 27 14:11:52.105495 2018] [core:error] [pid 41356] (13)Permission denied: [client 1.2.3.4:55713] AH00035: access to /index.html denied (filesystem path '/path/to/home') because search permissions are missing on a component of the path

try

ps -efZ | grep http


and check the httpd process, on which TYPE (httpd_t) it's running:

system_u:system_r:httpd_t:s0 root 37203 1 0 Feb28 ? 00:00:03 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 37206 37203 0 Feb28 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND


then you have to change the type of your file to be served

ls -Z /path/to/index.html
-rw-r--r--. admrun admrun unconfined_u:object_r:default_t:s0 /path/to/index.html

then you do

chcon -t httpd_t /path/to/index.html

if you get

chcon: failed to change context of "/path/to/myfile" to "˜unconfined_u:object_r:httpd_t:s": Permission denied

it's because httpd_t is a PROCESS type, not a FILE type ( see http://danwalsh.livejournal.com/54803.html )


see here https://linux.die.net/man/8/httpd_selinux complete documentation of types


However it's better to change the context for the folder rather than for the individual files:


# semanage fcontext -a -t httpd_sys_content_t "/path/to(/.*)?"
# restorecon -R -v /path/to




see also "man semanage-fcontext" and https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/security-enhanced_linux/sect-security-enhanced_linux-selinux_contexts_labeling_files-persistent_changes_semanage_fcontext


in Puppet (pueah) you can use https://github.com/voxpupuli/puppet-selinux and a clause like:


selinux::fcontext { '/path/to':
path => '/path/to(/.*)?',
setype => 'httpd_sys_content_t',
}






Thursday, February 22, 2018

Apache!

Docs http://httpd.apache.org/docs/2.4/

Docker image https://hub.docker.com/_/httpd/

mkdir myapp
cd myapp
docker run -dit --name my-apache-app -p 8080:80 httpd:2.4

http://localhost:8080/index.html should display "it works"


To install on Centos7:
sudo yum update
sudo yum install httpd
sudo systemctl start httpd.service
sudo systemctl enable httpd.service

and configuration file is /etc/httpd/conf/httpd.conf, files in /var/www/html/
sudo chmod 777 /var/www/html/
vi /var/www/html/index.html
http://localhost:80

Directives docs http://httpd.apache.org/docs/2.4/mod/directives.html

Virtualhost directive http://httpd.apache.org/docs/2.4/mod/core.html#virtualhost



Interesting article on Nginx vs Apache https://poweruphosting.com/blog/apache-vs-nginx/


To debug:
/usr/sbin/httpd -t
/usr/sbin/httpd -t -f /u01/app/mware/httpd/conf/jboss.conf
/usr/sbin/httpd -e debug
/usr/sbin/httpd -M
/usr/sbin/httpd -S (Priceless! to dump current configuration)






Tuesday, February 20, 2018

groovysh and X11

Running groovysh I get this error:


java.awt.AWTError: Can't connect to X11 window server using 'myserver:0.0' as the value of the DISPLAY variable

Really weird.... I could fix it only by "unset DISPLAY".

Complete stacktrace is:


java.awt.AWTError: Can't connect to X11 window server using ':0' as the value of the DISPLAY variable.
at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
at sun.awt.X11GraphicsEnvironment.access$200(X11GraphicsEnvironment.java:65)
at sun.awt.X11GraphicsEnvironment$1.run(X11GraphicsEnvironment.java:115)
at java.security.AccessController.doPrivileged(Native Method)
at sun.awt.X11GraphicsEnvironment.<clinit>(X11GraphicsEnvironment.java:74)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at java.awt.GraphicsEnvironment.createGE(GraphicsEnvironment.java:103)
at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:82)
at sun.awt.X11.XToolkit.<clinit>(XToolkit.java:126)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at java.awt.Toolkit$2.run(Toolkit.java:860)
at java.awt.Toolkit$2.run(Toolkit.java:855)
at java.security.AccessController.doPrivileged(Native Method)
at java.awt.Toolkit.getDefaultToolkit(Toolkit.java:854)
at java.awt.Desktop.isDesktopSupported(Desktop.java:169)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1850)
at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3758)
at org.codehaus.groovy.runtime.callsite.ClassMetaClassGetPropertySite.getProperty(ClassMetaClassGetPropertySite.java:51)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:296)
at org.codehaus.groovy.tools.shell.commands.DocCommand.<clinit>(DocCommand.groovy:57)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:235)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:247)
at org.codehaus.groovy.tools.shell.util.DefaultCommandsRegistrar.register(DefaultCommandsRegistrar.groovy:82)
at org.codehaus.groovy.tools.shell.util.DefaultCommandsRegistrar$register.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
at org.codehaus.groovy.tools.shell.Groovysh$_createDefaultRegistrar_closure3.doCall(Groovysh.groovy:116)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:42)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at org.codehaus.groovy.tools.shell.Groovysh.<init>(Groovysh.groovy:103)
at org.codehaus.groovy.tools.shell.Groovysh.<init>(Groovysh.groovy:122)
at org.codehaus.groovy.tools.shell.Groovysh.<init>(Groovysh.groovy:126)
at org.codehaus.groovy.tools.shell.Groovysh.<init>(Groovysh.groovy:130)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:235)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:247)
at org.codehaus.groovy.tools.shell.Main.<init>(Main.groovy:57)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:235)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:247)
at org.codehaus.groovy.tools.shell.Main.main(Main.groovy:151)