Hello Fediverse
After several years of not blogging, I've started writing the occasional post, but this time on the Fediverse. Visit my new blog on wordsmith.social:
After several years of not blogging, I've started writing the occasional post, but this time on the Fediverse. Visit my new blog on wordsmith.social:
Posted by
Glyn
at
5:32 PM
0
comments
Following last week's public launch of the Go-2 project, this post describes the first release and invites contributions. Go-2 is a simplified, extended subset of Google's Go programming language which addresses many of Go's short-comings long recognized by the community. Some of these gaps were highlighted recently in a blog by Gary Willoughby, particularly the lack of generics.
Steve Powell and I are experimenting with a minimal DI convention for Go which simplifies how we construct values of Go interfaces and use mocks of dependencies during testing.
Posted by
Glyn
at
3:41 PM
0
comments
Labels: dependency injection, golang
In order to use libcontainer as the basis for a new Warden backend, it needs upgrading. The requirements for a Container API over and above what libcontainer already provides are:
1. Multiple user processes: It must be possible to run multiple user processes in the same Container, either serially or in parallel. All user processes must run in the Container’s namespaces and control groups (so that they are all subject to the same isolation requirements and resource limits). User processes are peers in the sense that they share a common parent and one may terminate without terminating any others.
2. Container life cycle: It must be possible to create a new Container with no user processes. A Container should continue to exist after user processes have terminated.
3. Dynamic reconfiguration: It must be possible to reconfigure the Container after it has been created. There are some fundamental limitations in what can be reconfigured, but these must be kept to a bare minimum. In particular, it must be possible to reconfigure the Container’s control groups and network settings.
4. Container file system: It must be possible to share a single read-only root file system across multiple Container instances. A Container’s file system must be updatable and any updates made in one Container instance must not be visible to other Container instances.
5. Copying and streaming files: It must be possible to copy files and directories between the host and Container file systems. It must also be possible to stream files from the Container’s file system back to the host’s, for example to tail a log file.
Some of these requirements turn out to be beyond the scope of libcontainer as envisaged by its maintainers. In particular, since libcontainer's only consumer is Docker and Docker deals with file system layers, libcontainer avoids managing the read-write layer necessary to satisfy requirement 4. Requirement 5 is closely related to requirement 4.
Similarly, naming and managing collections of Container instances is deemed to be out of scope for libcontainer. So we envisage building an "ideal" Container API at a higher level than libcontainer and reusing libcontainer to provide the core function for a single Container:
Posted by
Glyn
at
4:07 PM
0
comments
Labels: CloudFoundry, docker, libcontainer
Posted by
Glyn
at
1:23 PM
10
comments
Labels: CloudFoundry, docker, libcontainer, warden
After discussing Better error handling idioms in Go and casting around a while, nothing turned up which was ideally suited to our project, so a colleague and I implemented the gerror package which captures stack traces when errors are created and enables errors to be identified without relying on the error message content.
So how does it look to a user? The first code to use it is a fileutils package which implements a file copy function in pure Go (no "shelling out" to cp). Let's take a look at a typical piece of error handling:
src, err := os.Open(source)
if err != nil {
return gerror.NewFromError(ErrOpeningSourceDir, err)
}
What does this achieve over and above the normal Go idiom of simply returning err if it is non-nil?
Firstly, it captures a stack trace in the error which appears when the error is logged (see below for an example). This gives the full context of the error which, in a large project, avoids guesswork and saves time locating the source of the error.
Secondly, it associates a "tag", in the form of an error identifier, with the error. Callers can use the tag if they want to check for particular errors programmatically:
gerr := fileutils.Copy(destPath, srcPath)
if gerr.EqualTag(fileutils.ErrOpeningSourceDir) {
...
}
Thirdly, the resultant error conforms to the builtin error interface and so can be returned or passed around wherever an error is expected.
Fourthly, by defining a function's error return type to be gerror.Gerror, the compiler prevents a "vanilla" error being returned accidentally from the function, which is useful when we want to ensure that all errors have stack traces and tags.
So how are error identifier tags defined? It's easy, as this code from fileutils shows:
type ErrorId int
const (
ErrFileNotFound ErrorId = iota
ErrOpeningSourceDir
...
)
Note that this has an advantage over the approach of using variables to refer to specific errors - variables can be overwritten (see this example of issue 7885), whereas constants cannot.
When errors are constructed, the gerror package stores the tag and its type. Both the tag and its type are included in the error string (returned, as usual, by the Error method) and are used when checking for equality in the EqualTag method.
The tag type is logically of the form package.Type which could be ambiguous if two packages had the same name, but the stack trace avoids the ambiguity. For example the following stack trace of a "file not found" error makes it clear that the tag type fileutils.ErrorId refers to the type in the package github.com/cf-guardian/guardian/kernel/fileutils:
0 fileutils.ErrorId: Error caused by: lstat /tmp/fileutils_test-027950024/src.file: no such file or directory
goroutine 8 [running]:
github.com/cf-guardian/guardian/gerror.NewFromError(0xe49a0, 0x0, 0x3484c8, 0xc21000aa80, 0x3484c8, ...)
/Users/gnormington/go/src/github.com/cf-guardian/guardian/gerror/gerror.go:68 +0x8d
github.com/cf-guardian/guardian/kernel/fileutils.fileMode(0xc21000a960, 0x26, 0xc21000a9c0, 0x29, 0x0)
/Users/gnormington/go/src/github.com/cf-guardian/guardian/kernel/fileutils/fileutils.go:196 +0x6b
github.com/cf-guardian/guardian/kernel/fileutils.doCopy(0xc21000a9c0, 0x29, 0xc21000a960, 0x26, 0xc21000a960, ...)
/Users/gnormington/go/src/github.com/cf-guardian/guardian/kernel/fileutils/fileutils.go:68 +0x87
github.com/cf-guardian/guardian/kernel/fileutils.Copy(0xc21000a9c0, 0x29, 0xc21000a960, 0x26, 0x29, ...)
/Users/gnormington/go/src/github.com/cf-guardian/guardian/kernel/fileutils/fileutils.go:61 +0x14f
...
The gerror package is available as open source on github and is licensed under the Apache v2 license. It's really a starting point and others are free to use it "as is" or adapt it to their own needs. If you have an improvement you think we might like, please read our contribution guidelines and send us a pull request.
Posted by
Glyn
at
2:25 PM
0
comments
Labels: diagnostics, error, FFDC, golang
How often have you seen, or written, Go code like this?
"open someFile: No such file or directory"
2009/11/10 23:00:00 "open someFile: No such file or directory"
goroutine 1 [running]:
main.main()
/tmpfs/gosandbox-xxx/prog.go:15 +0xe0
runtime.main()
/tmp/sandbox/go/src/pkg/runtime/proc.c:220 +0x1c0
runtime.goexit()
/tmp/sandbox/go/src/pkg/runtime/proc.c:1394
It is the error implementation's responsibility to summarize the context.but doesn't address the difficulty of large codebases where the immediate program context isn't always sufficient to diagnose problems.
Posted by
Glyn
at
10:23 AM
9
comments
Labels: diagnostics, error, FFDC, golang, logging
In the previous post, I mentioned a use case for the Virgo buildpack of running Virgo as an Ubuntu Juju charm. With some advice from the guys at Canonical, for which I'm grateful, a first prototype is now working.
The purpose of a charm is to instantiate a service in a cloud. I'm testing on Amazon EC2, although the charm should run without change on other clouds. The crucial contents of a charm are a simple metadata description and a series of hooks to control the lifecycle of the service associated with the charm and its relationships with other entities in the cloud.
So far, I've implemented two simple hooks. An install hook downloads and installs a JRE and Virgo as well as a test application. It does this by installing the test application and then running the Virgo buildpack compile operation against the application, which in turn downloads and installs a suitable JRE and Virgo (actually, Virgo Server for Apache Tomcat). A start hook starts Virgo using a command similar to that output by running the Virgo buildpack release operation against the test application.
The following pieces of work are necessary to tidy up the prototype:
Posted by
Glyn
at
3:37 AM
1 comments
Labels: Buildpack, charm, CloudFoundry, Java, Juju, OSGi, Ubuntu, Virgo
I'm no longer leading the Virgo project, but I am still fond of Virgo, so I thought I would update the Virgo buildpack (previously mentioned in this blog) in my own time to re-base it on the current Java buildpack.
It now inherits all the benefits of the Java buildpack (more here):
Posted by
Glyn
at
6:22 AM
0
comments
Labels: Buildpack, charm, CloudFoundry, Java, Juju, OSGi, Ubuntu, Virgo
We are using Code Climate to check the quality of the Ruby code in our Cloud Foundry Java buildpack. It's an excellent tool, but some improvements would really help.
Posted by
Glyn
at
8:54 AM
1 comments
The recent Virgo community survey showed quite a bit of interest in running Virgo in the cloud. With CloudFoundry's forthcoming "buildpack" support, this was relatively easy to achieve.
A Virgo buildpack is available on github - see the README for detailed information. It currently supports two types of application: web applications or "overlays". A web application may be a standard WAR file or an OSGi Web Application Bundle. An overlay is a pair of directories -- pickup for the application(s) to be deployed and repository/usr for any additional dependencies not already provided by Virgo -- which are placed in an instance of Virgo Server for Apache Tomcat.
The support for buildpacks should ship later this month - see the CloudFoundry roadmap.
Posted by
Glyn
at
4:55 PM
0
comments
Labels: cloud, CloudFoundry, OSGi, Virgo
Thanks to the ninety-seven people who filled in the Virgo survey. The survey is now closed and the results are in. I'll summarise the results here, but the raw data (in Open Document Spreadsheet format) are available for anyone who wants more detail.
88% of respondents are on Virgo 3.5.0 or later while only 5% are still using SpringSource dm Server.
Posted by
Glyn
at
4:18 PM
0
comments
Neil Bartlett's blog of this title is shocking because it shows how slow to adopt proven technology the computing industry is.
David Parnas wrote his seminal paper "On the Criteria To Be Used in Decomposing Systems into Modules" (available here) in 1972. A large transaction processing monitor was modularised in the 1980's because the cost of servicing it was spiralling out of control. (Precise specifications were written for the new modules to clean up the interfaces and minimise dependencies on module internals, but that's another story.)
The OSGi module system for Java has been mature for at least five years, possibly longer depending on how you count it. Most of the major Java application servers are now constructed of OSGi modules and a number of them expose OSGi for applications to use. And yet we still see complaints such as the one Neil quotes. It seems application developers are stuck in their ways or stuck on systems which prevent them from using modularity.
Of course, modularity will eventually be adopted by all business critical software. There's really no rational alternative. But how long it will take is quite another matter.
Posted by
Glyn
at
1:50 PM
0
comments
Labels: OSGi
The recording of Dan North's recent talk on "Embracing Uncertainty" set me thinking again about what I like and dislike about agile methods such as scrum. As we end the 157th consecutive sprint of the Virgo project, I certainly appreciate the focus and sense of making progress that each sprint brings.
But what I really dislike are spikes.
The principle of a spike sounds fine: carve out some time to do some exploratory work. But I soon find myself too constrained by a spike. One definition of a spike is (emphasis added):
"a story that cannot be estimated until a development team runs a timeboxed investigation. The output of a spike story is an estimate for the original story."There are some assumptions buried in that definition which I think show some of the problems:
Posted by
Glyn
at
4:20 PM
4
comments
I kept seeing the following pop-up during Java based builds on Mac OS X:
Posted by
Glyn
at
1:56 PM
0
comments
IBM, Paremus, Rebaze, Red Hat, and VMware/SpringSource, with interested parties Peter Kriens and SAP, have submitted an Eclipse Bundle Recipes project proposal aiming to provide a repository of OSGi bundle templates for open source JARs. The intention is that this will supersede the SpringSource Enterprise Bundle Repository (EBR).
It's a couple of years since we ran the first Virgo survey and the project has moved on a lot since then. So we've just published a new Eclipse Virgo Community Survey. If you use Virgo, I'd really appreciate it if you could take a few minutes to complete the survey. If you are short of time, please just fill in the first six questions and skip the rest.
Question 12 is a fun quiz about the use of OSGi in application servers. You'll probably find it interesting even if you have no interest in Virgo. We'll provide the answers in a few weeks time along with the survey results.
Here's the survey if you want to get going right away.
Virgo 3.6.0 is available for download. Although the release includes many small enhancements and bug fixes, some major new features are worth highlighting and there is one smaller one I'd like to draw to the attention of Windows users.
Mike Milinkovich, the Executive Director of the Eclipse Foundation, spoke of Virgo 3.6.0 in his recent JAX interview:
"A third important milestone was SAP shipping its Netweaver Cloud offering based on the Eclipse Virgo project. Having a major vendor basing such a significant product on Eclipse runtime technologies is a great endorsement of the work that the Eclipse RT community has been doing for several years."So, let's look at the new features.